1 /*-
2 * Copyright (c) 2001-2003 Allan Saddi <allan@saddi.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $Id: sha512.c 680 2003-07-25 21:58:07Z asaddi $
27 */
28
29 /*
30 * Define WORDS_BIGENDIAN if compiling on a big-endian architecture.
31 *
32 * Define SHA512_TEST to test the implementation using the NIST's
33 * sample messages. The output should be:
34 *
35 * ddaf35a193617aba cc417349ae204131 12e6fa4e89a97ea2 0a9eeee64b55d39a
36 * 2192992a274fc1a8 36ba3c23a3feebbd 454d4423643ce80e 2a9ac94fa54ca49f
37 * 8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018
38 * 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
39 * e718483d0ce76964 4e2e42c7bc15b463 8e1f98b13b204428 5632a803afa973eb
40 * de0ff244877ea60a 4cb0432ce577c31b eb009c5c2c49aa2e 4eadb217ad8cc09b
41 */
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif /* HAVE_CONFIG_H */
46
47 #if HAVE_INTTYPES_H
48 # include <inttypes.h>
49 #else
50 # if HAVE_STDINT_H
51 # include <stdint.h>
52 # endif
53 #endif
54
55 #include <string.h>
56
57 #include "sha512.h"
58
59 #ifndef lint
60 static const char rcsid[] =
61 "$Id: sha512.c 680 2003-07-25 21:58:07Z asaddi $";
62 #endif /* !lint */
63
64 #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
65 #define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
66 #define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
67 #define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
68
69 #define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
70 #define Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
71 #define SIGMA0(x) (ROTR64((x), 28) ^ ROTR64((x), 34) ^ ROTR64((x), 39))
72 #define SIGMA1(x) (ROTR64((x), 14) ^ ROTR64((x), 18) ^ ROTR64((x), 41))
73 #define sigma0(x) (ROTR64((x), 1) ^ ROTR64((x), 8) ^ ((x) >> 7))
74 #define sigma1(x) (ROTR64((x), 19) ^ ROTR64((x), 61) ^ ((x) >> 6))
75
76 #define DO_ROUND() { \
77 t1 = h + SIGMA1(e) + Ch(e, f, g) + *(Kp++) + *(W++); \
78 t2 = SIGMA0(a) + Maj(a, b, c); \
79 h = g; \
80 g = f; \
81 f = e; \
82 e = d + t1; \
83 d = c; \
84 c = b; \
85 b = a; \
86 a = t1 + t2; \
87 }
88
89 static const uint64_t K[80] = {
90 0x428a2f98d728ae22LL, 0x7137449123ef65cdLL,
91 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL,
92 0x3956c25bf348b538LL, 0x59f111f1b605d019LL,
93 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL,
94 0xd807aa98a3030242LL, 0x12835b0145706fbeLL,
95 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL,
96 0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL,
97 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL,
98 0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL,
99 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL,
100 0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL,
101 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL,
102 0x983e5152ee66dfabLL, 0xa831c66d2db43210LL,
103 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL,
104 0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL,
105 0x06ca6351e003826fLL, 0x142929670a0e6e70LL,
106 0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL,
107 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL,
108 0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL,
109 0x81c2c92e47edaee6LL, 0x92722c851482353bLL,
110 0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL,
111 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL,
112 0xd192e819d6ef5218LL, 0xd69906245565a910LL,
113 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL,
114 0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL,
115 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL,
116 0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL,
117 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL,
118 0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL,
119 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL,
120 0x90befffa23631e28LL, 0xa4506cebde82bde9LL,
121 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL,
122 0xca273eceea26619cLL, 0xd186b8c721c0c207LL,
123 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL,
124 0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL,
125 0x113f9804bef90daeLL, 0x1b710b35131c471bLL,
126 0x28db77f523047d84LL, 0x32caab7b40c72493LL,
127 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL,
128 0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL,
129 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL
130 };
131
132 #ifndef RUNTIME_ENDIAN
133
134 #ifdef WORDS_BIGENDIAN
135
136 #define BYTESWAP(x) (x)
137 #define BYTESWAP64(x) (x)
138
139 #else /* WORDS_BIGENDIAN */
140
141 #define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
142 (ROTL((x), 8) & 0x00ff00ffL))
143 #define BYTESWAP64(x) _byteswap64(x)
144
_byteswap64(uint64_t x)145 static inline uint64_t _byteswap64(uint64_t x)
146 {
147 uint32_t a = x >> 32;
148 uint32_t b = (uint32_t) x;
149 return ((uint64_t) BYTESWAP(b) << 32) | (uint64_t) BYTESWAP(a);
150 }
151
152 #endif /* WORDS_BIGENDIAN */
153
154 #else /* !RUNTIME_ENDIAN */
155
156 #define BYTESWAP(x) _byteswap(sc->littleEndian, x)
157 #define BYTESWAP64(x) _byteswap64(sc->littleEndian, x)
158
159 #define _BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
160 (ROTL((x), 8) & 0x00ff00ffL))
161 #define _BYTESWAP64(x) __byteswap64(x)
162
__byteswap64(uint64_t x)163 static inline uint64_t __byteswap64(uint64_t x)
164 {
165 uint32_t a = x >> 32;
166 uint32_t b = (uint32_t) x;
167 return ((uint64_t) _BYTESWAP(b) << 32) | (uint64_t) _BYTESWAP(a);
168 }
169
_byteswap(int littleEndian,uint32_t x)170 static inline uint32_t _byteswap(int littleEndian, uint32_t x)
171 {
172 if (!littleEndian)
173 return x;
174 else
175 return _BYTESWAP(x);
176 }
177
_byteswap64(int littleEndian,uint64_t x)178 static inline uint64_t _byteswap64(int littleEndian, uint64_t x)
179 {
180 if (!littleEndian)
181 return x;
182 else
183 return _BYTESWAP64(x);
184 }
185
setEndian(int * littleEndianp)186 static inline void setEndian(int *littleEndianp)
187 {
188 union {
189 uint32_t w;
190 uint8_t b[4];
191 } endian;
192
193 endian.w = 1L;
194 *littleEndianp = endian.b[0] != 0;
195 }
196
197 #endif /* !RUNTIME_ENDIAN */
198
199 static const uint8_t padding[128] = {
200 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
216 };
217
218 void
SHA512Init(SHA512Context * sc)219 SHA512Init (SHA512Context *sc)
220 {
221 #ifdef RUNTIME_ENDIAN
222 setEndian (&sc->littleEndian);
223 #endif /* RUNTIME_ENDIAN */
224
225 sc->totalLength[0] = 0LL;
226 sc->totalLength[1] = 0LL;
227 sc->hash[0] = 0x6a09e667f3bcc908LL;
228 sc->hash[1] = 0xbb67ae8584caa73bLL;
229 sc->hash[2] = 0x3c6ef372fe94f82bLL;
230 sc->hash[3] = 0xa54ff53a5f1d36f1LL;
231 sc->hash[4] = 0x510e527fade682d1LL;
232 sc->hash[5] = 0x9b05688c2b3e6c1fLL;
233 sc->hash[6] = 0x1f83d9abfb41bd6bLL;
234 sc->hash[7] = 0x5be0cd19137e2179LL;
235 sc->bufferLength = 0L;
236 }
237
238 static void
burnStack(int size)239 burnStack (int size)
240 {
241 char buf[128];
242
243 memset (buf, 0, sizeof (buf));
244 size -= sizeof (buf);
245 if (size > 0)
246 burnStack (size);
247 }
248
249 static void
SHA512Guts(SHA512Context * sc,const uint64_t * cbuf)250 SHA512Guts (SHA512Context *sc, const uint64_t *cbuf)
251 {
252 uint64_t buf[80];
253 uint64_t *W, *W2, *W7, *W15, *W16;
254 uint64_t a, b, c, d, e, f, g, h;
255 uint64_t t1, t2;
256 const uint64_t *Kp;
257 int i;
258
259 W = buf;
260
261 for (i = 15; i >= 0; i--) {
262 *(W++) = BYTESWAP64(*cbuf);
263 cbuf++;
264 }
265
266 W16 = &buf[0];
267 W15 = &buf[1];
268 W7 = &buf[9];
269 W2 = &buf[14];
270
271 for (i = 63; i >= 0; i--) {
272 *(W++) = sigma1(*W2) + *(W7++) + sigma0(*W15) + *(W16++);
273 W2++;
274 W15++;
275 }
276
277 a = sc->hash[0];
278 b = sc->hash[1];
279 c = sc->hash[2];
280 d = sc->hash[3];
281 e = sc->hash[4];
282 f = sc->hash[5];
283 g = sc->hash[6];
284 h = sc->hash[7];
285
286 Kp = K;
287 W = buf;
288
289 for (i = 79; i >= 0; i--)
290 DO_ROUND();
291
292 sc->hash[0] += a;
293 sc->hash[1] += b;
294 sc->hash[2] += c;
295 sc->hash[3] += d;
296 sc->hash[4] += e;
297 sc->hash[5] += f;
298 sc->hash[6] += g;
299 sc->hash[7] += h;
300 }
301
302 void
SHA512Update(SHA512Context * sc,const void * vdata,uint32_t len)303 SHA512Update (SHA512Context *sc, const void *vdata, uint32_t len)
304 {
305 const uint8_t *data = vdata;
306 uint32_t bufferBytesLeft;
307 uint32_t bytesToCopy;
308 uint64_t carryCheck;
309 int needBurn = 0;
310
311 #ifdef SHA512_FAST_COPY
312 if (sc->bufferLength) {
313 bufferBytesLeft = 128L - sc->bufferLength;
314
315 bytesToCopy = bufferBytesLeft;
316 if (bytesToCopy > len)
317 bytesToCopy = len;
318
319 memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
320
321 carryCheck = sc->totalLength[1];
322 sc->totalLength[1] += bytesToCopy * 8L;
323 if (sc->totalLength[1] < carryCheck)
324 sc->totalLength[0]++;
325
326 sc->bufferLength += bytesToCopy;
327 data += bytesToCopy;
328 len -= bytesToCopy;
329
330 if (sc->bufferLength == 128L) {
331 SHA512Guts (sc, sc->buffer.words);
332 needBurn = 1;
333 sc->bufferLength = 0L;
334 }
335 }
336
337 while (len > 127) {
338 carryCheck = sc->totalLength[1];
339 sc->totalLength[1] += 1024L;
340 if (sc->totalLength[1] < carryCheck)
341 sc->totalLength[0]++;
342
343 SHA512Guts (sc, data);
344 needBurn = 1;
345
346 data += 128L;
347 len -= 128L;
348 }
349
350 if (len) {
351 memcpy (&sc->buffer.bytes[sc->bufferLength], data, len);
352
353 carryCheck = sc->totalLength[1];
354 sc->totalLength[1] += len * 8L;
355 if (sc->totalLength[1] < carryCheck)
356 sc->totalLength[0]++;
357
358 sc->bufferLength += len;
359 }
360 #else /* SHA512_FAST_COPY */
361 while (len) {
362 bufferBytesLeft = 128L - sc->bufferLength;
363
364 bytesToCopy = bufferBytesLeft;
365 if (bytesToCopy > len)
366 bytesToCopy = len;
367
368 memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
369
370 carryCheck = sc->totalLength[1];
371 sc->totalLength[1] += bytesToCopy * 8L;
372 if (sc->totalLength[1] < carryCheck)
373 sc->totalLength[0]++;
374
375 sc->bufferLength += bytesToCopy;
376 data += bytesToCopy;
377 len -= bytesToCopy;
378
379 if (sc->bufferLength == 128L) {
380 SHA512Guts (sc, sc->buffer.words);
381 needBurn = 1;
382 sc->bufferLength = 0L;
383 }
384 }
385 #endif /* SHA512_FAST_COPY */
386
387 if (needBurn)
388 burnStack (sizeof (uint64_t[90]) + sizeof (uint64_t *[6]) + sizeof (int));
389 }
390
391 void
SHA512Final(SHA512Context * sc,uint8_t hash[SHA512_HASH_SIZE])392 SHA512Final (SHA512Context *sc, uint8_t hash[SHA512_HASH_SIZE])
393 {
394 uint32_t bytesToPad;
395 uint64_t lengthPad[2];
396 int i;
397
398 bytesToPad = 240L - sc->bufferLength;
399 if (bytesToPad > 128L)
400 bytesToPad -= 128L;
401
402 lengthPad[0] = BYTESWAP64(sc->totalLength[0]);
403 lengthPad[1] = BYTESWAP64(sc->totalLength[1]);
404
405 SHA512Update (sc, padding, bytesToPad);
406 SHA512Update (sc, lengthPad, 16L);
407
408 if (hash) {
409 for (i = 0; i < SHA512_HASH_WORDS; i++) {
410 #ifdef SHA384_FAST_COPY
411 *((uint64_t *) hash) = BYTESWAP64(sc->hash[i]);
412 #else /* SHA384_FAST_COPY */
413 hash[0] = (uint8_t) (sc->hash[i] >> 56);
414 hash[1] = (uint8_t) (sc->hash[i] >> 48);
415 hash[2] = (uint8_t) (sc->hash[i] >> 40);
416 hash[3] = (uint8_t) (sc->hash[i] >> 32);
417 hash[4] = (uint8_t) (sc->hash[i] >> 24);
418 hash[5] = (uint8_t) (sc->hash[i] >> 16);
419 hash[6] = (uint8_t) (sc->hash[i] >> 8);
420 hash[7] = (uint8_t) sc->hash[i];
421 #endif /* SHA384_FAST_COPY */
422 hash += 8;
423 }
424 }
425 }
426
427 #ifdef SHA512_TEST
428
429 #include <stdio.h>
430 #include <stdlib.h>
431 #include <string.h>
432
433 int
main(int argc,char * argv[])434 main (int argc, char *argv[])
435 {
436 SHA512Context foo;
437 uint8_t hash[SHA512_HASH_SIZE];
438 char buf[1000];
439 int i;
440
441 SHA512Init (&foo);
442 SHA512Update (&foo, "abc", 3);
443 SHA512Final (&foo, hash);
444
445 for (i = 0; i < SHA512_HASH_SIZE;) {
446 printf ("%02x", hash[i++]);
447 if (!(i % 8))
448 printf (" ");
449 if (!(i % 32))
450 printf ("\n");
451 }
452
453 SHA512Init (&foo);
454 SHA512Update (&foo,
455 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
456 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
457 112);
458 SHA512Final (&foo, hash);
459
460 for (i = 0; i < SHA512_HASH_SIZE;) {
461 printf ("%02x", hash[i++]);
462 if (!(i % 8))
463 printf (" ");
464 if (!(i % 32))
465 printf ("\n");
466 }
467
468 SHA512Init (&foo);
469 memset (buf, 'a', sizeof (buf));
470 for (i = 0; i < 1000; i++)
471 SHA512Update (&foo, buf, sizeof (buf));
472 SHA512Final (&foo, hash);
473
474 for (i = 0; i < SHA512_HASH_SIZE;) {
475 printf ("%02x", hash[i++]);
476 if (!(i % 8))
477 printf (" ");
478 if (!(i % 32))
479 printf ("\n");
480 }
481
482 exit (0);
483 }
484
485 #endif /* SHA512_TEST */
486