]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/CyaSSL/ctaocrypt/src/sha512.c
Update CyaSSL to latest version.
[freertos] / FreeRTOS-Plus / Source / CyaSSL / ctaocrypt / src / sha512.c
index f14efecff9c25d61d53d67a9665cd6cd87ec568b..40086949b54fac12136e098f6633002b2b5c77e6 100644 (file)
@@ -1,6 +1,6 @@
 /* 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
@@ -44,7 +53,7 @@
 #endif /* min */
 
 
-void InitSha512(Sha512* sha512)
+int InitSha512(Sha512* sha512)
 {
     sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
     sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
@@ -58,6 +67,8 @@ void InitSha512(Sha512* sha512)
     sha512->buffLen = 0;
     sha512->loLen   = 0;
     sha512->hiLen   = 0;
+
+    return 0;
 }
 
 
@@ -134,24 +145,44 @@ static const word64 K512[80] = {
        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 */
 
@@ -165,8 +196,14 @@ static void Transform(Sha512* sha512)
     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;
 }
 
 
@@ -178,7 +215,7 @@ static INLINE void AddLength(Sha512* sha512, word32 len)
 }
 
 
-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;
@@ -192,21 +229,28 @@ void Sha512Update(Sha512* sha512, const byte* data, word32 len)
         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 */
 
@@ -220,7 +264,10 @@ void Sha512Final(Sha512* sha512, byte* hash)
         #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);
@@ -238,20 +285,55 @@ void Sha512Final(Sha512* sha512, byte* hash)
     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);
@@ -265,27 +347,49 @@ void InitSha384(Sha384* sha384)
     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 */
 
@@ -299,8 +403,14 @@ static void Transform384(Sha384* sha384)
     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;
 }
 
 
@@ -312,7 +422,7 @@ static INLINE void AddLength384(Sha384* sha384, word32 len)
 }
 
 
-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;
@@ -326,21 +436,28 @@ void Sha384Update(Sha384* sha384, const byte* data, word32 len)
         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 */
 
@@ -354,7 +471,10 @@ void Sha384Final(Sha384* sha384, byte* hash)
         #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);
@@ -372,13 +492,49 @@ void Sha384Final(Sha384* sha384, byte* hash)
     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 */