This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

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