3 * Copyright (C) 2006-2014 wolfSSL Inc.
5 * This file is part of CyaSSL.
7 * CyaSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CyaSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <cyassl/ctaocrypt/settings.h>
31 /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
32 #define FIPS_NO_WRAPPERS
35 #include <cyassl/ctaocrypt/sha512.h>
36 #include <cyassl/ctaocrypt/logging.h>
37 #include <cyassl/ctaocrypt/error-crypt.h>
40 #include <cyassl/ctaocrypt/misc.h>
42 #include <ctaocrypt/src/misc.c>
48 static INLINE word32 min(word32 a, word32 b)
56 int InitSha512(Sha512* sha512)
58 sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
59 sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
60 sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b);
61 sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1);
62 sha512->digest[4] = W64LIT(0x510e527fade682d1);
63 sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f);
64 sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b);
65 sha512->digest[7] = W64LIT(0x5be0cd19137e2179);
75 static const word64 K512[80] = {
76 W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
77 W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
78 W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
79 W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
80 W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
81 W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
82 W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
83 W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
84 W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
85 W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
86 W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
87 W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
88 W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
89 W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
90 W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
91 W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
92 W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
93 W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
94 W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
95 W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
96 W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
97 W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
98 W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
99 W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
100 W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
101 W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
102 W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
103 W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
104 W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
105 W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
106 W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
107 W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
108 W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
109 W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
110 W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
111 W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
112 W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
113 W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
114 W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
115 W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
119 #define blk0(i) (W[i] = sha512->buffer[i])
120 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
122 #define Ch(x,y,z) (z^(x&(y^z)))
123 #define Maj(x,y,z) ((x&y)|(z&(x|y)))
125 #define a(i) T[(0-i)&7]
126 #define b(i) T[(1-i)&7]
127 #define c(i) T[(2-i)&7]
128 #define d(i) T[(3-i)&7]
129 #define e(i) T[(4-i)&7]
130 #define f(i) T[(5-i)&7]
131 #define g(i) T[(6-i)&7]
132 #define h(i) T[(7-i)&7]
134 #define S0(x) (rotrFixed64(x,28)^rotrFixed64(x,34)^rotrFixed64(x,39))
135 #define S1(x) (rotrFixed64(x,14)^rotrFixed64(x,18)^rotrFixed64(x,41))
136 #define s0(x) (rotrFixed64(x,1)^rotrFixed64(x,8)^(x>>7))
137 #define s1(x) (rotrFixed64(x,19)^rotrFixed64(x,61)^(x>>6))
139 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk0(i));\
140 d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
142 #define blk384(i) (W[i] = sha384->buffer[i])
144 #define R2(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk384(i));\
145 d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
148 static int Transform(Sha512* sha512)
150 const word64* K = K512;
155 #ifdef CYASSL_SMALL_STACK
158 W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
165 /* Copy digest to working vars */
166 XMEMCPY(T, sha512->digest, sizeof(T));
169 /* over twice as small, but 50% slower */
170 /* 80 operations, not unrolled */
171 for (j = 0; j < 80; j += 16) {
173 for (m = 0; m < 16; m++) { /* braces needed here for macros {} */
178 /* 80 operations, partially loop unrolled */
179 for (j = 0; j < 80; j += 16) {
180 R( 0); R( 1); R( 2); R( 3);
181 R( 4); R( 5); R( 6); R( 7);
182 R( 8); R( 9); R(10); R(11);
183 R(12); R(13); R(14); R(15);
185 #endif /* USE_SLOW_SHA2 */
187 /* Add the working vars back into digest */
189 sha512->digest[0] += a(0);
190 sha512->digest[1] += b(0);
191 sha512->digest[2] += c(0);
192 sha512->digest[3] += d(0);
193 sha512->digest[4] += e(0);
194 sha512->digest[5] += f(0);
195 sha512->digest[6] += g(0);
196 sha512->digest[7] += h(0);
199 XMEMSET(W, 0, sizeof(word64) * 16);
200 XMEMSET(T, 0, sizeof(T));
202 #ifdef CYASSL_SMALL_STACK
203 XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
210 static INLINE void AddLength(Sha512* sha512, word32 len)
212 word32 tmp = sha512->loLen;
213 if ( (sha512->loLen += len) < tmp)
214 sha512->hiLen++; /* carry low to high */
218 int Sha512Update(Sha512* sha512, const byte* data, word32 len)
220 /* do block size increments */
221 byte* local = (byte*)sha512->buffer;
224 word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen);
225 XMEMCPY(&local[sha512->buffLen], data, add);
227 sha512->buffLen += add;
231 if (sha512->buffLen == SHA512_BLOCK_SIZE) {
234 #ifdef LITTLE_ENDIAN_ORDER
235 ByteReverseWords64(sha512->buffer, sha512->buffer,
238 ret = Transform(sha512);
242 AddLength(sha512, SHA512_BLOCK_SIZE);
250 int Sha512Final(Sha512* sha512, byte* hash)
252 byte* local = (byte*)sha512->buffer;
255 AddLength(sha512, sha512->buffLen); /* before adding pads */
257 local[sha512->buffLen++] = 0x80; /* add 1 */
260 if (sha512->buffLen > SHA512_PAD_SIZE) {
261 XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen);
262 sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen;
264 #ifdef LITTLE_ENDIAN_ORDER
265 ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE);
267 ret = Transform(sha512);
273 XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen);
275 /* put lengths in bits */
276 sha512->hiLen = (sha512->loLen >> (8*sizeof(sha512->loLen) - 3)) +
277 (sha512->hiLen << 3);
278 sha512->loLen = sha512->loLen << 3;
281 #ifdef LITTLE_ENDIAN_ORDER
282 ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE);
284 /* ! length ordering dependent on digest endian type ! */
285 sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
286 sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
288 ret = Transform(sha512);
292 #ifdef LITTLE_ENDIAN_ORDER
293 ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE);
295 XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE);
297 return InitSha512(sha512); /* reset state */
301 int Sha512Hash(const byte* data, word32 len, byte* hash)
304 #ifdef CYASSL_SMALL_STACK
310 #ifdef CYASSL_SMALL_STACK
311 sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER);
316 if ((ret = InitSha512(sha512)) != 0) {
317 CYASSL_MSG("InitSha512 failed");
319 else if ((ret = Sha512Update(sha512, data, len)) != 0) {
320 CYASSL_MSG("Sha512Update failed");
322 else if ((ret = Sha512Final(sha512, hash)) != 0) {
323 CYASSL_MSG("Sha512Final failed");
326 #ifdef CYASSL_SMALL_STACK
327 XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
336 int InitSha384(Sha384* sha384)
338 sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
339 sha384->digest[1] = W64LIT(0x629a292a367cd507);
340 sha384->digest[2] = W64LIT(0x9159015a3070dd17);
341 sha384->digest[3] = W64LIT(0x152fecd8f70e5939);
342 sha384->digest[4] = W64LIT(0x67332667ffc00b31);
343 sha384->digest[5] = W64LIT(0x8eb44a8768581511);
344 sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7);
345 sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4);
355 static int Transform384(Sha384* sha384)
357 const word64* K = K512;
362 #ifdef CYASSL_SMALL_STACK
365 W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
372 /* Copy digest to working vars */
373 XMEMCPY(T, sha384->digest, sizeof(T));
376 /* over twice as small, but 50% slower */
377 /* 80 operations, not unrolled */
378 for (j = 0; j < 80; j += 16) {
380 for (m = 0; m < 16; m++) { /* braces needed for macros {} */
385 /* 80 operations, partially loop unrolled */
386 for (j = 0; j < 80; j += 16) {
387 R2( 0); R2( 1); R2( 2); R2( 3);
388 R2( 4); R2( 5); R2( 6); R2( 7);
389 R2( 8); R2( 9); R2(10); R2(11);
390 R2(12); R2(13); R2(14); R2(15);
392 #endif /* USE_SLOW_SHA2 */
394 /* Add the working vars back into digest */
396 sha384->digest[0] += a(0);
397 sha384->digest[1] += b(0);
398 sha384->digest[2] += c(0);
399 sha384->digest[3] += d(0);
400 sha384->digest[4] += e(0);
401 sha384->digest[5] += f(0);
402 sha384->digest[6] += g(0);
403 sha384->digest[7] += h(0);
406 XMEMSET(W, 0, sizeof(word64) * 16);
407 XMEMSET(T, 0, sizeof(T));
409 #ifdef CYASSL_SMALL_STACK
410 XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
417 static INLINE void AddLength384(Sha384* sha384, word32 len)
419 word32 tmp = sha384->loLen;
420 if ( (sha384->loLen += len) < tmp)
421 sha384->hiLen++; /* carry low to high */
425 int Sha384Update(Sha384* sha384, const byte* data, word32 len)
427 /* do block size increments */
428 byte* local = (byte*)sha384->buffer;
431 word32 add = min(len, SHA384_BLOCK_SIZE - sha384->buffLen);
432 XMEMCPY(&local[sha384->buffLen], data, add);
434 sha384->buffLen += add;
438 if (sha384->buffLen == SHA384_BLOCK_SIZE) {
441 #ifdef LITTLE_ENDIAN_ORDER
442 ByteReverseWords64(sha384->buffer, sha384->buffer,
445 ret = Transform384(sha384);
449 AddLength384(sha384, SHA384_BLOCK_SIZE);
457 int Sha384Final(Sha384* sha384, byte* hash)
459 byte* local = (byte*)sha384->buffer;
462 AddLength384(sha384, sha384->buffLen); /* before adding pads */
464 local[sha384->buffLen++] = 0x80; /* add 1 */
467 if (sha384->buffLen > SHA384_PAD_SIZE) {
468 XMEMSET(&local[sha384->buffLen], 0, SHA384_BLOCK_SIZE -sha384->buffLen);
469 sha384->buffLen += SHA384_BLOCK_SIZE - sha384->buffLen;
471 #ifdef LITTLE_ENDIAN_ORDER
472 ByteReverseWords64(sha384->buffer,sha384->buffer,SHA384_BLOCK_SIZE);
474 ret = Transform384(sha384);
480 XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen);
482 /* put lengths in bits */
483 sha384->hiLen = (sha384->loLen >> (8*sizeof(sha384->loLen) - 3)) +
484 (sha384->hiLen << 3);
485 sha384->loLen = sha384->loLen << 3;
488 #ifdef LITTLE_ENDIAN_ORDER
489 ByteReverseWords64(sha384->buffer, sha384->buffer, SHA384_PAD_SIZE);
491 /* ! length ordering dependent on digest endian type ! */
492 sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen;
493 sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen;
495 ret = Transform384(sha384);
499 #ifdef LITTLE_ENDIAN_ORDER
500 ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE);
502 XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE);
504 return InitSha384(sha384); /* reset state */
508 int Sha384Hash(const byte* data, word32 len, byte* hash)
511 #ifdef CYASSL_SMALL_STACK
517 #ifdef CYASSL_SMALL_STACK
518 sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER);
523 if ((ret = InitSha384(sha384)) != 0) {
524 CYASSL_MSG("InitSha384 failed");
526 else if ((ret = Sha384Update(sha384, data, len)) != 0) {
527 CYASSL_MSG("Sha384Update failed");
529 else if ((ret = Sha384Final(sha384, hash)) != 0) {
530 CYASSL_MSG("Sha384Final failed");
533 #ifdef CYASSL_SMALL_STACK
534 XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
540 #endif /* CYASSL_SHA384 */
542 #endif /* CYASSL_SHA512 */