d 0773d / CyaSSL

Dependents:   CyaSSL_Example

Fork of CyaSSL by wolf SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sha512.c Source File

sha512.c

00001 /* sha512.c
00002  *
00003  * Copyright (C) 2006-2014 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023     #include <config.h>
00024 #endif
00025 
00026 #include <cyassl/ctaocrypt/settings.h>
00027 
00028 #ifdef CYASSL_SHA512
00029 
00030 #ifdef HAVE_FIPS
00031     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
00032     #define FIPS_NO_WRAPPERS
00033 #endif
00034 
00035 #include <cyassl/ctaocrypt/sha512.h>
00036 #include <cyassl/ctaocrypt/error-crypt.h>
00037 #ifdef NO_INLINE
00038     #include <cyassl/ctaocrypt/misc.h>
00039 #else
00040     #include <ctaocrypt/src/misc.c>
00041 #endif
00042 
00043 
00044 #ifndef min
00045 
00046     static INLINE word32 min(word32 a, word32 b)
00047     {
00048         return a > b ? b : a;
00049     }
00050 
00051 #endif /* min */
00052 
00053 
00054 int InitSha512(Sha512* sha512)
00055 {
00056     sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
00057     sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
00058     sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b);
00059     sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1);
00060     sha512->digest[4] = W64LIT(0x510e527fade682d1);
00061     sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f);
00062     sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b);
00063     sha512->digest[7] = W64LIT(0x5be0cd19137e2179);
00064 
00065     sha512->buffLen = 0;
00066     sha512->loLen   = 0;
00067     sha512->hiLen   = 0;
00068 
00069     return 0;
00070 }
00071 
00072 
00073 static const word64 K512[80] = {
00074     W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
00075     W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
00076     W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
00077     W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
00078     W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
00079     W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
00080     W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
00081     W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
00082     W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
00083     W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
00084     W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
00085     W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
00086     W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
00087     W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
00088     W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
00089     W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
00090     W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
00091     W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
00092     W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
00093     W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
00094     W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
00095     W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
00096     W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
00097     W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
00098     W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
00099     W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
00100     W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
00101     W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
00102     W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
00103     W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
00104     W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
00105     W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
00106     W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
00107     W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
00108     W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
00109     W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
00110     W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
00111     W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
00112     W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
00113     W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
00114 };
00115 
00116 
00117 #define blk0(i) (W[i] = sha512->buffer[i])
00118 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
00119 
00120 #define Ch(x,y,z) (z^(x&(y^z)))
00121 #define Maj(x,y,z) ((x&y)|(z&(x|y)))
00122 
00123 #define a(i) T[(0-i)&7]
00124 #define b(i) T[(1-i)&7]
00125 #define c(i) T[(2-i)&7]
00126 #define d(i) T[(3-i)&7]
00127 #define e(i) T[(4-i)&7]
00128 #define f(i) T[(5-i)&7]
00129 #define g(i) T[(6-i)&7]
00130 #define h(i) T[(7-i)&7]
00131 
00132 #define S0(x) (rotrFixed64(x,28)^rotrFixed64(x,34)^rotrFixed64(x,39))
00133 #define S1(x) (rotrFixed64(x,14)^rotrFixed64(x,18)^rotrFixed64(x,41))
00134 #define s0(x) (rotrFixed64(x,1)^rotrFixed64(x,8)^(x>>7))
00135 #define s1(x) (rotrFixed64(x,19)^rotrFixed64(x,61)^(x>>6))
00136 
00137 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk0(i));\
00138     d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
00139 
00140 #define blk384(i) (W[i] = sha384->buffer[i])
00141 
00142 #define R2(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk384(i));\
00143     d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
00144 
00145 
00146 static int Transform(Sha512* sha512)
00147 {
00148     const word64* K = K512;
00149 
00150     word32 j;
00151     word64 T[8];
00152 
00153 #ifdef CYASSL_SMALL_STACK
00154     word64* W;
00155 
00156     W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00157     if (W == NULL)
00158         return MEMORY_E;
00159 #else
00160     word64 W[16];
00161 #endif
00162 
00163     /* Copy digest to working vars */
00164     XMEMCPY(T, sha512->digest, sizeof(T));
00165 
00166 #ifdef USE_SLOW_SHA2
00167     /* over twice as small, but 50% slower */
00168     /* 80 operations, not unrolled */
00169     for (j = 0; j < 80; j += 16) {
00170         int m; 
00171         for (m = 0; m < 16; m++) { /* braces needed here for macros {} */
00172             R(m);
00173         }
00174     }
00175 #else
00176     /* 80 operations, partially loop unrolled */
00177     for (j = 0; j < 80; j += 16) {
00178         R( 0); R( 1); R( 2); R( 3);
00179         R( 4); R( 5); R( 6); R( 7);
00180         R( 8); R( 9); R(10); R(11);
00181         R(12); R(13); R(14); R(15);
00182     }
00183 #endif /* USE_SLOW_SHA2 */
00184 
00185     /* Add the working vars back into digest */
00186 
00187     sha512->digest[0] += a(0);
00188     sha512->digest[1] += b(0);
00189     sha512->digest[2] += c(0);
00190     sha512->digest[3] += d(0);
00191     sha512->digest[4] += e(0);
00192     sha512->digest[5] += f(0);
00193     sha512->digest[6] += g(0);
00194     sha512->digest[7] += h(0);
00195 
00196     /* Wipe variables */
00197     XMEMSET(W, 0, sizeof(word64) * 16);
00198     XMEMSET(T, 0, sizeof(T));
00199 
00200 #ifdef CYASSL_SMALL_STACK
00201     XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00202 #endif
00203 
00204     return 0;
00205 }
00206 
00207 
00208 static INLINE void AddLength(Sha512* sha512, word32 len)
00209 {
00210     word32 tmp = sha512->loLen;
00211     if ( (sha512->loLen += len) < tmp)
00212         sha512->hiLen++;                       /* carry low to high */
00213 }
00214 
00215 
00216 int Sha512Update(Sha512* sha512, const byte* data, word32 len)
00217 {
00218     /* do block size increments */
00219     byte* local = (byte*)sha512->buffer;
00220 
00221     while (len) {
00222         word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen);
00223         XMEMCPY(&local[sha512->buffLen], data, add);
00224 
00225         sha512->buffLen += add;
00226         data         += add;
00227         len          -= add;
00228 
00229         if (sha512->buffLen == SHA512_BLOCK_SIZE) {
00230             int ret;
00231 
00232             #ifdef LITTLE_ENDIAN_ORDER
00233                 ByteReverseWords64(sha512->buffer, sha512->buffer,
00234                                    SHA512_BLOCK_SIZE);
00235             #endif
00236             ret = Transform(sha512);
00237             if (ret != 0)
00238                 return ret;
00239 
00240             AddLength(sha512, SHA512_BLOCK_SIZE);
00241             sha512->buffLen = 0;
00242         }
00243     }
00244     return 0;
00245 }
00246 
00247 
00248 int Sha512Final(Sha512* sha512, byte* hash)
00249 {
00250     byte* local = (byte*)sha512->buffer;
00251     int ret;
00252 
00253     AddLength(sha512, sha512->buffLen);               /* before adding pads */
00254 
00255     local[sha512->buffLen++] = 0x80;  /* add 1 */
00256 
00257     /* pad with zeros */
00258     if (sha512->buffLen > SHA512_PAD_SIZE) {
00259         XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen);
00260         sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen;
00261 
00262         #ifdef LITTLE_ENDIAN_ORDER
00263             ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE);
00264         #endif
00265         ret = Transform(sha512);
00266         if (ret != 0)
00267             return ret;
00268 
00269         sha512->buffLen = 0;
00270     }
00271     XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen);
00272    
00273     /* put lengths in bits */
00274     sha512->hiLen = (sha512->loLen >> (8*sizeof(sha512->loLen) - 3)) + 
00275                  (sha512->hiLen << 3);
00276     sha512->loLen = sha512->loLen << 3;
00277 
00278     /* store lengths */
00279     #ifdef LITTLE_ENDIAN_ORDER
00280         ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE);
00281     #endif
00282     /* ! length ordering dependent on digest endian type ! */
00283     sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
00284     sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
00285 
00286     ret = Transform(sha512);
00287     if (ret != 0)
00288         return ret;
00289 
00290     #ifdef LITTLE_ENDIAN_ORDER
00291         ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE);
00292     #endif
00293     XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE);
00294 
00295     return InitSha512(sha512);  /* reset state */
00296 }
00297 
00298 
00299 
00300 #ifdef CYASSL_SHA384
00301 
00302 int InitSha384(Sha384* sha384)
00303 {
00304     sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
00305     sha384->digest[1] = W64LIT(0x629a292a367cd507);
00306     sha384->digest[2] = W64LIT(0x9159015a3070dd17);
00307     sha384->digest[3] = W64LIT(0x152fecd8f70e5939);
00308     sha384->digest[4] = W64LIT(0x67332667ffc00b31);
00309     sha384->digest[5] = W64LIT(0x8eb44a8768581511);
00310     sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7);
00311     sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4);
00312 
00313     sha384->buffLen = 0;
00314     sha384->loLen   = 0;
00315     sha384->hiLen   = 0;
00316 
00317     return 0;
00318 }
00319 
00320 
00321 static int Transform384(Sha384* sha384)
00322 {
00323     const word64* K = K512;
00324 
00325     word32 j;
00326     word64 T[8];
00327 
00328 #ifdef CYASSL_SMALL_STACK
00329     word64* W;
00330 
00331     W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00332     if (W == NULL)
00333         return MEMORY_E;
00334 #else
00335     word64 W[16];
00336 #endif
00337 
00338     /* Copy digest to working vars */
00339     XMEMCPY(T, sha384->digest, sizeof(T));
00340 
00341 #ifdef USE_SLOW_SHA2
00342     /* over twice as small, but 50% slower */
00343     /* 80 operations, not unrolled */
00344     for (j = 0; j < 80; j += 16) {
00345         int m;
00346         for (m = 0; m < 16; m++) {  /* braces needed for macros {} */
00347             R2(m);
00348         }
00349     }
00350 #else
00351     /* 80 operations, partially loop unrolled */
00352     for (j = 0; j < 80; j += 16) {
00353         R2( 0); R2( 1); R2( 2); R2( 3);
00354         R2( 4); R2( 5); R2( 6); R2( 7);
00355         R2( 8); R2( 9); R2(10); R2(11);
00356         R2(12); R2(13); R2(14); R2(15);
00357     }
00358 #endif /* USE_SLOW_SHA2 */
00359 
00360     /* Add the working vars back into digest */
00361 
00362     sha384->digest[0] += a(0);
00363     sha384->digest[1] += b(0);
00364     sha384->digest[2] += c(0);
00365     sha384->digest[3] += d(0);
00366     sha384->digest[4] += e(0);
00367     sha384->digest[5] += f(0);
00368     sha384->digest[6] += g(0);
00369     sha384->digest[7] += h(0);
00370 
00371     /* Wipe variables */
00372     XMEMSET(W, 0, sizeof(word64) * 16);
00373     XMEMSET(T, 0, sizeof(T));
00374 
00375 #ifdef CYASSL_SMALL_STACK
00376     XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00377 #endif
00378 
00379     return 0;
00380 }
00381 
00382 
00383 static INLINE void AddLength384(Sha384* sha384, word32 len)
00384 {
00385     word32 tmp = sha384->loLen;
00386     if ( (sha384->loLen += len) < tmp)
00387         sha384->hiLen++;                       /* carry low to high */
00388 }
00389 
00390 
00391 int Sha384Update(Sha384* sha384, const byte* data, word32 len)
00392 {
00393     /* do block size increments */
00394     byte* local = (byte*)sha384->buffer;
00395 
00396     while (len) {
00397         word32 add = min(len, SHA384_BLOCK_SIZE - sha384->buffLen);
00398         XMEMCPY(&local[sha384->buffLen], data, add);
00399 
00400         sha384->buffLen += add;
00401         data         += add;
00402         len          -= add;
00403 
00404         if (sha384->buffLen == SHA384_BLOCK_SIZE) {
00405             int ret;
00406 
00407             #ifdef LITTLE_ENDIAN_ORDER
00408                 ByteReverseWords64(sha384->buffer, sha384->buffer,
00409                                    SHA384_BLOCK_SIZE);
00410             #endif
00411             ret = Transform384(sha384);
00412             if (ret != 0)
00413                 return ret;
00414 
00415             AddLength384(sha384, SHA384_BLOCK_SIZE);
00416             sha384->buffLen = 0;
00417         }
00418     }
00419     return 0;
00420 }
00421 
00422 
00423 int Sha384Final(Sha384* sha384, byte* hash)
00424 {
00425     byte* local = (byte*)sha384->buffer;
00426     int ret;
00427 
00428     AddLength384(sha384, sha384->buffLen);              /* before adding pads */
00429 
00430     local[sha384->buffLen++] = 0x80;  /* add 1 */
00431 
00432     /* pad with zeros */
00433     if (sha384->buffLen > SHA384_PAD_SIZE) {
00434         XMEMSET(&local[sha384->buffLen], 0, SHA384_BLOCK_SIZE -sha384->buffLen);
00435         sha384->buffLen += SHA384_BLOCK_SIZE - sha384->buffLen;
00436 
00437         #ifdef LITTLE_ENDIAN_ORDER
00438             ByteReverseWords64(sha384->buffer,sha384->buffer,SHA384_BLOCK_SIZE);
00439         #endif
00440         ret = Transform384(sha384);
00441         if (ret !=  0)
00442             return ret;
00443 
00444         sha384->buffLen = 0;
00445     }
00446     XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen);
00447    
00448     /* put lengths in bits */
00449     sha384->hiLen = (sha384->loLen >> (8*sizeof(sha384->loLen) - 3)) + 
00450                  (sha384->hiLen << 3);
00451     sha384->loLen = sha384->loLen << 3;
00452 
00453     /* store lengths */
00454     #ifdef LITTLE_ENDIAN_ORDER
00455         ByteReverseWords64(sha384->buffer, sha384->buffer, SHA384_PAD_SIZE);
00456     #endif
00457     /* ! length ordering dependent on digest endian type ! */
00458     sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen;
00459     sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen;
00460 
00461     ret = Transform384(sha384);
00462     if (ret != 0)
00463         return ret;
00464 
00465     #ifdef LITTLE_ENDIAN_ORDER
00466         ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE);
00467     #endif
00468     XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE);
00469 
00470     return InitSha384(sha384);  /* reset state */
00471 }
00472 
00473 #endif /* CYASSL_SHA384 */
00474 
00475 #endif /* CYASSL_SHA512 */
00476