wolf SSL / CyaSSL-2.9.4

Dependents:  

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-2013 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 #ifdef NO_INLINE
00037     #include <cyassl/ctaocrypt/misc.h>
00038 #else
00039     #include <ctaocrypt/src/misc.c>
00040 #endif
00041 
00042 
00043 #ifndef min
00044 
00045     static INLINE word32 min(word32 a, word32 b)
00046     {
00047         return a > b ? b : a;
00048     }
00049 
00050 #endif /* min */
00051 
00052 
00053 int InitSha512(Sha512* sha512)
00054 {
00055     sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
00056     sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
00057     sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b);
00058     sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1);
00059     sha512->digest[4] = W64LIT(0x510e527fade682d1);
00060     sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f);
00061     sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b);
00062     sha512->digest[7] = W64LIT(0x5be0cd19137e2179);
00063 
00064     sha512->buffLen = 0;
00065     sha512->loLen   = 0;
00066     sha512->hiLen   = 0;
00067 
00068     return 0;
00069 }
00070 
00071 
00072 static const word64 K512[80] = {
00073     W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
00074     W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
00075     W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
00076     W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
00077     W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
00078     W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
00079     W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
00080     W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
00081     W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
00082     W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
00083     W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
00084     W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
00085     W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
00086     W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
00087     W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
00088     W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
00089     W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
00090     W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
00091     W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
00092     W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
00093     W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
00094     W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
00095     W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
00096     W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
00097     W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
00098     W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
00099     W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
00100     W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
00101     W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
00102     W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
00103     W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
00104     W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
00105     W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
00106     W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
00107     W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
00108     W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
00109     W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
00110     W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
00111     W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
00112     W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
00113 };
00114 
00115 
00116 #define blk0(i) (W[i] = sha512->buffer[i])
00117 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
00118 
00119 #define Ch(x,y,z) (z^(x&(y^z)))
00120 #define Maj(x,y,z) ((x&y)|(z&(x|y)))
00121 
00122 #define a(i) T[(0-i)&7]
00123 #define b(i) T[(1-i)&7]
00124 #define c(i) T[(2-i)&7]
00125 #define d(i) T[(3-i)&7]
00126 #define e(i) T[(4-i)&7]
00127 #define f(i) T[(5-i)&7]
00128 #define g(i) T[(6-i)&7]
00129 #define h(i) T[(7-i)&7]
00130 
00131 #define S0(x) (rotrFixed64(x,28)^rotrFixed64(x,34)^rotrFixed64(x,39))
00132 #define S1(x) (rotrFixed64(x,14)^rotrFixed64(x,18)^rotrFixed64(x,41))
00133 #define s0(x) (rotrFixed64(x,1)^rotrFixed64(x,8)^(x>>7))
00134 #define s1(x) (rotrFixed64(x,19)^rotrFixed64(x,61)^(x>>6))
00135 
00136 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk0(i));\
00137     d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
00138 
00139 #define blk384(i) (W[i] = sha384->buffer[i])
00140 
00141 #define R2(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk384(i));\
00142     d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
00143 
00144 
00145 static void Transform(Sha512* sha512)
00146 {
00147     const word64* K = K512;
00148 
00149     word32 j;
00150     word64 W[16];
00151     word64 T[8];
00152 
00153     /* Copy digest to working vars */
00154     XMEMCPY(T, sha512->digest, sizeof(T));
00155 
00156 #ifdef USE_SLOW_SHA2
00157     /* over twice as small, but 50% slower */
00158     /* 80 operations, not unrolled */
00159     for (j = 0; j < 80; j += 16) {
00160         int m; 
00161         for (m = 0; m < 16; m++) { /* braces needed here for macros {} */
00162             R(m);
00163         }
00164     }
00165 #else
00166     /* 80 operations, partially loop unrolled */
00167     for (j = 0; j < 80; j += 16) {
00168         R( 0); R( 1); R( 2); R( 3);
00169         R( 4); R( 5); R( 6); R( 7);
00170         R( 8); R( 9); R(10); R(11);
00171         R(12); R(13); R(14); R(15);
00172     }
00173 #endif /* USE_SLOW_SHA2 */
00174 
00175     /* Add the working vars back into digest */
00176 
00177     sha512->digest[0] += a(0);
00178     sha512->digest[1] += b(0);
00179     sha512->digest[2] += c(0);
00180     sha512->digest[3] += d(0);
00181     sha512->digest[4] += e(0);
00182     sha512->digest[5] += f(0);
00183     sha512->digest[6] += g(0);
00184     sha512->digest[7] += h(0);
00185 
00186     /* Wipe variables */
00187     XMEMSET(W, 0, sizeof(W));
00188     XMEMSET(T, 0, sizeof(T));
00189 }
00190 
00191 
00192 static INLINE void AddLength(Sha512* sha512, word32 len)
00193 {
00194     word32 tmp = sha512->loLen;
00195     if ( (sha512->loLen += len) < tmp)
00196         sha512->hiLen++;                       /* carry low to high */
00197 }
00198 
00199 
00200 int Sha512Update(Sha512* sha512, const byte* data, word32 len)
00201 {
00202     /* do block size increments */
00203     byte* local = (byte*)sha512->buffer;
00204 
00205     while (len) {
00206         word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen);
00207         XMEMCPY(&local[sha512->buffLen], data, add);
00208 
00209         sha512->buffLen += add;
00210         data         += add;
00211         len          -= add;
00212 
00213         if (sha512->buffLen == SHA512_BLOCK_SIZE) {
00214             #ifdef LITTLE_ENDIAN_ORDER
00215                 ByteReverseWords64(sha512->buffer, sha512->buffer,
00216                                    SHA512_BLOCK_SIZE);
00217             #endif
00218             Transform(sha512);
00219             AddLength(sha512, SHA512_BLOCK_SIZE);
00220             sha512->buffLen = 0;
00221         }
00222     }
00223     return 0;
00224 }
00225 
00226 
00227 int Sha512Final(Sha512* sha512, byte* hash)
00228 {
00229     byte* local = (byte*)sha512->buffer;
00230 
00231     AddLength(sha512, sha512->buffLen);               /* before adding pads */
00232 
00233     local[sha512->buffLen++] = 0x80;  /* add 1 */
00234 
00235     /* pad with zeros */
00236     if (sha512->buffLen > SHA512_PAD_SIZE) {
00237         XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen);
00238         sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen;
00239 
00240         #ifdef LITTLE_ENDIAN_ORDER
00241             ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE);
00242         #endif
00243         Transform(sha512);
00244         sha512->buffLen = 0;
00245     }
00246     XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen);
00247    
00248     /* put lengths in bits */
00249     sha512->hiLen = (sha512->loLen >> (8*sizeof(sha512->loLen) - 3)) + 
00250                  (sha512->hiLen << 3);
00251     sha512->loLen = sha512->loLen << 3;
00252 
00253     /* store lengths */
00254     #ifdef LITTLE_ENDIAN_ORDER
00255         ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE);
00256     #endif
00257     /* ! length ordering dependent on digest endian type ! */
00258     sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
00259     sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
00260 
00261     Transform(sha512);
00262     #ifdef LITTLE_ENDIAN_ORDER
00263         ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE);
00264     #endif
00265     XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE);
00266 
00267     return InitSha512(sha512);  /* reset state */
00268 }
00269 
00270 
00271 
00272 #ifdef CYASSL_SHA384
00273 
00274 int InitSha384(Sha384* sha384)
00275 {
00276     sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
00277     sha384->digest[1] = W64LIT(0x629a292a367cd507);
00278     sha384->digest[2] = W64LIT(0x9159015a3070dd17);
00279     sha384->digest[3] = W64LIT(0x152fecd8f70e5939);
00280     sha384->digest[4] = W64LIT(0x67332667ffc00b31);
00281     sha384->digest[5] = W64LIT(0x8eb44a8768581511);
00282     sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7);
00283     sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4);
00284 
00285     sha384->buffLen = 0;
00286     sha384->loLen   = 0;
00287     sha384->hiLen   = 0;
00288 
00289     return 0;
00290 }
00291 
00292 
00293 static void Transform384(Sha384* sha384)
00294 {
00295     const word64* K = K512;
00296 
00297     word32 j;
00298     word64 W[16];
00299     word64 T[8];
00300 
00301     /* Copy digest to working vars */
00302     XMEMCPY(T, sha384->digest, sizeof(T));
00303 
00304 #ifdef USE_SLOW_SHA2
00305     /* over twice as small, but 50% slower */
00306     /* 80 operations, not unrolled */
00307     for (j = 0; j < 80; j += 16) {
00308         int m;
00309         for (m = 0; m < 16; m++) {  /* braces needed for macros {} */
00310             R2(m);
00311         }
00312     }
00313 #else
00314     /* 80 operations, partially loop unrolled */
00315     for (j = 0; j < 80; j += 16) {
00316         R2( 0); R2( 1); R2( 2); R2( 3);
00317         R2( 4); R2( 5); R2( 6); R2( 7);
00318         R2( 8); R2( 9); R2(10); R2(11);
00319         R2(12); R2(13); R2(14); R2(15);
00320     }
00321 #endif /* USE_SLOW_SHA2 */
00322 
00323     /* Add the working vars back into digest */
00324 
00325     sha384->digest[0] += a(0);
00326     sha384->digest[1] += b(0);
00327     sha384->digest[2] += c(0);
00328     sha384->digest[3] += d(0);
00329     sha384->digest[4] += e(0);
00330     sha384->digest[5] += f(0);
00331     sha384->digest[6] += g(0);
00332     sha384->digest[7] += h(0);
00333 
00334     /* Wipe variables */
00335     XMEMSET(W, 0, sizeof(W));
00336     XMEMSET(T, 0, sizeof(T));
00337 }
00338 
00339 
00340 static INLINE void AddLength384(Sha384* sha384, word32 len)
00341 {
00342     word32 tmp = sha384->loLen;
00343     if ( (sha384->loLen += len) < tmp)
00344         sha384->hiLen++;                       /* carry low to high */
00345 }
00346 
00347 
00348 int Sha384Update(Sha384* sha384, const byte* data, word32 len)
00349 {
00350     /* do block size increments */
00351     byte* local = (byte*)sha384->buffer;
00352 
00353     while (len) {
00354         word32 add = min(len, SHA384_BLOCK_SIZE - sha384->buffLen);
00355         XMEMCPY(&local[sha384->buffLen], data, add);
00356 
00357         sha384->buffLen += add;
00358         data         += add;
00359         len          -= add;
00360 
00361         if (sha384->buffLen == SHA384_BLOCK_SIZE) {
00362             #ifdef LITTLE_ENDIAN_ORDER
00363                 ByteReverseWords64(sha384->buffer, sha384->buffer,
00364                                    SHA384_BLOCK_SIZE);
00365             #endif
00366             Transform384(sha384);
00367             AddLength384(sha384, SHA384_BLOCK_SIZE);
00368             sha384->buffLen = 0;
00369         }
00370     }
00371     return 0;
00372 }
00373 
00374 
00375 int Sha384Final(Sha384* sha384, byte* hash)
00376 {
00377     byte* local = (byte*)sha384->buffer;
00378 
00379     AddLength384(sha384, sha384->buffLen);              /* before adding pads */
00380 
00381     local[sha384->buffLen++] = 0x80;  /* add 1 */
00382 
00383     /* pad with zeros */
00384     if (sha384->buffLen > SHA384_PAD_SIZE) {
00385         XMEMSET(&local[sha384->buffLen], 0, SHA384_BLOCK_SIZE -sha384->buffLen);
00386         sha384->buffLen += SHA384_BLOCK_SIZE - sha384->buffLen;
00387 
00388         #ifdef LITTLE_ENDIAN_ORDER
00389             ByteReverseWords64(sha384->buffer,sha384->buffer,SHA384_BLOCK_SIZE);
00390         #endif
00391         Transform384(sha384);
00392         sha384->buffLen = 0;
00393     }
00394     XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen);
00395    
00396     /* put lengths in bits */
00397     sha384->hiLen = (sha384->loLen >> (8*sizeof(sha384->loLen) - 3)) + 
00398                  (sha384->hiLen << 3);
00399     sha384->loLen = sha384->loLen << 3;
00400 
00401     /* store lengths */
00402     #ifdef LITTLE_ENDIAN_ORDER
00403         ByteReverseWords64(sha384->buffer, sha384->buffer, SHA384_PAD_SIZE);
00404     #endif
00405     /* ! length ordering dependent on digest endian type ! */
00406     sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen;
00407     sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen;
00408 
00409     Transform384(sha384);
00410     #ifdef LITTLE_ENDIAN_ORDER
00411         ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE);
00412     #endif
00413     XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE);
00414 
00415     return InitSha384(sha384);  /* reset state */
00416 }
00417 
00418 #endif /* CYASSL_SHA384 */
00419 
00420 #endif /* CYASSL_SHA512 */