/* sha512.c
*
- * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
+ * Copyright (C) 2006-2014 wolfSSL Inc.
*
* This file is part of CyaSSL.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#include <cyassl/ctaocrypt/settings.h>
#ifdef CYASSL_SHA512
+#ifdef HAVE_FIPS
+ /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+ #define FIPS_NO_WRAPPERS
+#endif
+
#include <cyassl/ctaocrypt/sha512.h>
+#include <cyassl/ctaocrypt/logging.h>
+#include <cyassl/ctaocrypt/error-crypt.h>
+
#ifdef NO_INLINE
#include <cyassl/ctaocrypt/misc.h>
#else
#endif /* min */
-void InitSha512(Sha512* sha512)
+int InitSha512(Sha512* sha512)
{
sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
sha512->buffLen = 0;
sha512->loLen = 0;
sha512->hiLen = 0;
+
+ return 0;
}
d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
-static void Transform(Sha512* sha512)
+static int Transform(Sha512* sha512)
{
const word64* K = K512;
word32 j;
- word64 W[16];
word64 T[8];
+#ifdef CYASSL_SMALL_STACK
+ word64* W;
+
+ W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (W == NULL)
+ return MEMORY_E;
+#else
+ word64 W[16];
+#endif
+
/* Copy digest to working vars */
XMEMCPY(T, sha512->digest, sizeof(T));
- /* 64 operations, partially loop unrolled */
+#ifdef USE_SLOW_SHA2
+ /* over twice as small, but 50% slower */
+ /* 80 operations, not unrolled */
+ for (j = 0; j < 80; j += 16) {
+ int m;
+ for (m = 0; m < 16; m++) { /* braces needed here for macros {} */
+ R(m);
+ }
+ }
+#else
+ /* 80 operations, partially loop unrolled */
for (j = 0; j < 80; j += 16) {
R( 0); R( 1); R( 2); R( 3);
R( 4); R( 5); R( 6); R( 7);
R( 8); R( 9); R(10); R(11);
R(12); R(13); R(14); R(15);
}
+#endif /* USE_SLOW_SHA2 */
/* Add the working vars back into digest */
sha512->digest[7] += h(0);
/* Wipe variables */
- XMEMSET(W, 0, sizeof(W));
+ XMEMSET(W, 0, sizeof(word64) * 16);
XMEMSET(T, 0, sizeof(T));
+
+#ifdef CYASSL_SMALL_STACK
+ XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return 0;
}
}
-void Sha512Update(Sha512* sha512, const byte* data, word32 len)
+int Sha512Update(Sha512* sha512, const byte* data, word32 len)
{
/* do block size increments */
byte* local = (byte*)sha512->buffer;
len -= add;
if (sha512->buffLen == SHA512_BLOCK_SIZE) {
+ int ret;
+
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(sha512->buffer, sha512->buffer,
SHA512_BLOCK_SIZE);
#endif
- Transform(sha512);
+ ret = Transform(sha512);
+ if (ret != 0)
+ return ret;
+
AddLength(sha512, SHA512_BLOCK_SIZE);
sha512->buffLen = 0;
}
}
+ return 0;
}
-void Sha512Final(Sha512* sha512, byte* hash)
+int Sha512Final(Sha512* sha512, byte* hash)
{
byte* local = (byte*)sha512->buffer;
+ int ret;
AddLength(sha512, sha512->buffLen); /* before adding pads */
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE);
#endif
- Transform(sha512);
+ ret = Transform(sha512);
+ if (ret != 0)
+ return ret;
+
sha512->buffLen = 0;
}
XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen);
sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
- Transform(sha512);
+ ret = Transform(sha512);
+ if (ret != 0)
+ return ret;
+
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE);
#endif
XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE);
- InitSha512(sha512); /* reset state */
+ return InitSha512(sha512); /* reset state */
}
+int Sha512Hash(const byte* data, word32 len, byte* hash)
+{
+ int ret = 0;
+#ifdef CYASSL_SMALL_STACK
+ Sha512* sha512;
+#else
+ Sha512 sha512[1];
+#endif
+
+#ifdef CYASSL_SMALL_STACK
+ sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (sha512 == NULL)
+ return MEMORY_E;
+#endif
+
+ if ((ret = InitSha512(sha512)) != 0) {
+ CYASSL_MSG("InitSha512 failed");
+ }
+ else if ((ret = Sha512Update(sha512, data, len)) != 0) {
+ CYASSL_MSG("Sha512Update failed");
+ }
+ else if ((ret = Sha512Final(sha512, hash)) != 0) {
+ CYASSL_MSG("Sha512Final failed");
+ }
+
+#ifdef CYASSL_SMALL_STACK
+ XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return ret;
+}
+
#ifdef CYASSL_SHA384
-void InitSha384(Sha384* sha384)
+int InitSha384(Sha384* sha384)
{
sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
sha384->digest[1] = W64LIT(0x629a292a367cd507);
sha384->buffLen = 0;
sha384->loLen = 0;
sha384->hiLen = 0;
+
+ return 0;
}
-static void Transform384(Sha384* sha384)
+static int Transform384(Sha384* sha384)
{
const word64* K = K512;
word32 j;
- word64 W[16];
word64 T[8];
+#ifdef CYASSL_SMALL_STACK
+ word64* W;
+
+ W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (W == NULL)
+ return MEMORY_E;
+#else
+ word64 W[16];
+#endif
+
/* Copy digest to working vars */
XMEMCPY(T, sha384->digest, sizeof(T));
- /* 64 operations, partially loop unrolled */
+#ifdef USE_SLOW_SHA2
+ /* over twice as small, but 50% slower */
+ /* 80 operations, not unrolled */
+ for (j = 0; j < 80; j += 16) {
+ int m;
+ for (m = 0; m < 16; m++) { /* braces needed for macros {} */
+ R2(m);
+ }
+ }
+#else
+ /* 80 operations, partially loop unrolled */
for (j = 0; j < 80; j += 16) {
R2( 0); R2( 1); R2( 2); R2( 3);
R2( 4); R2( 5); R2( 6); R2( 7);
R2( 8); R2( 9); R2(10); R2(11);
R2(12); R2(13); R2(14); R2(15);
}
+#endif /* USE_SLOW_SHA2 */
/* Add the working vars back into digest */
sha384->digest[7] += h(0);
/* Wipe variables */
- XMEMSET(W, 0, sizeof(W));
+ XMEMSET(W, 0, sizeof(word64) * 16);
XMEMSET(T, 0, sizeof(T));
+
+#ifdef CYASSL_SMALL_STACK
+ XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return 0;
}
}
-void Sha384Update(Sha384* sha384, const byte* data, word32 len)
+int Sha384Update(Sha384* sha384, const byte* data, word32 len)
{
/* do block size increments */
byte* local = (byte*)sha384->buffer;
len -= add;
if (sha384->buffLen == SHA384_BLOCK_SIZE) {
+ int ret;
+
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(sha384->buffer, sha384->buffer,
SHA384_BLOCK_SIZE);
#endif
- Transform384(sha384);
+ ret = Transform384(sha384);
+ if (ret != 0)
+ return ret;
+
AddLength384(sha384, SHA384_BLOCK_SIZE);
sha384->buffLen = 0;
}
}
+ return 0;
}
-void Sha384Final(Sha384* sha384, byte* hash)
+int Sha384Final(Sha384* sha384, byte* hash)
{
byte* local = (byte*)sha384->buffer;
+ int ret;
AddLength384(sha384, sha384->buffLen); /* before adding pads */
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(sha384->buffer,sha384->buffer,SHA384_BLOCK_SIZE);
#endif
- Transform384(sha384);
+ ret = Transform384(sha384);
+ if (ret != 0)
+ return ret;
+
sha384->buffLen = 0;
}
XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen);
sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen;
sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen;
- Transform384(sha384);
+ ret = Transform384(sha384);
+ if (ret != 0)
+ return ret;
+
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE);
#endif
XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE);
- InitSha384(sha384); /* reset state */
+ return InitSha384(sha384); /* reset state */
+}
+
+
+int Sha384Hash(const byte* data, word32 len, byte* hash)
+{
+ int ret = 0;
+#ifdef CYASSL_SMALL_STACK
+ Sha384* sha384;
+#else
+ Sha384 sha384[1];
+#endif
+
+#ifdef CYASSL_SMALL_STACK
+ sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (sha384 == NULL)
+ return MEMORY_E;
+#endif
+
+ if ((ret = InitSha384(sha384)) != 0) {
+ CYASSL_MSG("InitSha384 failed");
+ }
+ else if ((ret = Sha384Update(sha384, data, len)) != 0) {
+ CYASSL_MSG("Sha384Update failed");
+ }
+ else if ((ret = Sha384Final(sha384, hash)) != 0) {
+ CYASSL_MSG("Sha384Final failed");
+ }
+
+#ifdef CYASSL_SMALL_STACK
+ XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return ret;
}
#endif /* CYASSL_SHA384 */