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
20 const 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 */
39 static const ulong64 K[80] = {
40 CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
41 CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
42 CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
43 CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
44 CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
45 CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
46 CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
47 CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
48 CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
49 CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
50 CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
51 CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
52 CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
53 CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
54 CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
55 CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
56 CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
57 CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
58 CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
59 CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
60 CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
61 CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
62 CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
63 CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
64 CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
65 CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
66 CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
67 CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
68 CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
69 CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
70 CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
71 CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
72 CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
73 CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
74 CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
75 CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
76 CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
77 CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
78 CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
79 CONST64(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
_sha512_compress(hash_state * md,unsigned char * buf)94 static int _sha512_compress(hash_state * md, unsigned char *buf)
95 #else
96 static 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
sha512_compress(hash_state * md,unsigned char * buf)161 static 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 */
sha512_init(hash_state * md)175 int 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 */
198 HASH_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 */
sha512_done(hash_state * md,unsigned char * out)206 int 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 */
sha512_test(void)261 int 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