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 sha256.c Source File

sha256.c

00001 /* sha256.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 
00023 /* code submitted by raphael.huck@efixo.com */
00024 
00025 #ifdef HAVE_CONFIG_H
00026     #include <config.h>
00027 #endif
00028 
00029 #include <cyassl/ctaocrypt/settings.h>
00030 
00031 #ifndef NO_SHA256
00032 
00033 #include <cyassl/ctaocrypt/sha256.h>
00034 #ifdef NO_INLINE
00035     #include <cyassl/ctaocrypt/misc.h>
00036 #else
00037     #include <ctaocrypt/src/misc.c>
00038 #endif
00039 
00040 
00041 #ifndef min
00042 
00043     static INLINE word32 min(word32 a, word32 b)
00044     {
00045         return a > b ? b : a;
00046     }
00047 
00048 #endif /* min */
00049 
00050 
00051 void InitSha256(Sha256* sha256)
00052 {
00053     sha256->digest[0] = 0x6A09E667L;
00054     sha256->digest[1] = 0xBB67AE85L;
00055     sha256->digest[2] = 0x3C6EF372L;
00056     sha256->digest[3] = 0xA54FF53AL;
00057     sha256->digest[4] = 0x510E527FL;
00058     sha256->digest[5] = 0x9B05688CL;
00059     sha256->digest[6] = 0x1F83D9ABL;
00060     sha256->digest[7] = 0x5BE0CD19L;
00061 
00062     sha256->buffLen = 0;
00063     sha256->loLen   = 0;
00064     sha256->hiLen   = 0;
00065 }
00066 
00067 static const word32 K[64] = {
00068     0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
00069     0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
00070     0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,
00071     0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
00072     0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,
00073     0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,
00074     0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,
00075     0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
00076     0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,
00077     0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,
00078     0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,
00079     0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
00080     0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
00081 };
00082 
00083 #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
00084 #define Maj(x,y,z)      (((x | y) & z) | (x & y))
00085 #define S(x, n)         rotrFixed(x, n)
00086 #define R(x, n)         (((x)&0xFFFFFFFFU)>>(n))
00087 #define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
00088 #define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
00089 #define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
00090 #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
00091 
00092 #define RND(a,b,c,d,e,f,g,h,i) \
00093      t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
00094      t1 = Sigma0(a) + Maj(a, b, c); \
00095      d += t0; \
00096      h  = t0 + t1;
00097 
00098 
00099 static void Transform(Sha256* sha256)
00100 {
00101     word32 S[8], W[64], t0, t1;
00102     int i;
00103 
00104     /* Copy context->state[] to working vars */
00105     for (i = 0; i < 8; i++)
00106         S[i] = sha256->digest[i];
00107 
00108     for (i = 0; i < 16; i++)
00109         W[i] = sha256->buffer[i];
00110 
00111     for (i = 16; i < 64; i++)
00112         W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];
00113 
00114     for (i = 0; i < 64; i += 8) {
00115         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
00116         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
00117         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
00118         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
00119         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
00120         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
00121         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
00122         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
00123     }
00124 
00125     /* Add the working vars back into digest state[] */
00126     for (i = 0; i < 8; i++) {
00127         sha256->digest[i] += S[i];
00128     }
00129 }
00130 
00131 
00132 static INLINE void AddLength(Sha256* sha256, word32 len)
00133 {
00134     word32 tmp = sha256->loLen;
00135     if ( (sha256->loLen += len) < tmp)
00136         sha256->hiLen++;                       /* carry low to high */
00137 }
00138 
00139 
00140 void Sha256Update(Sha256* sha256, const byte* data, word32 len)
00141 {
00142     /* do block size increments */
00143     byte* local = (byte*)sha256->buffer;
00144 
00145     while (len) {
00146         word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen);
00147         XMEMCPY(&local[sha256->buffLen], data, add);
00148 
00149         sha256->buffLen += add;
00150         data            += add;
00151         len             -= add;
00152 
00153         if (sha256->buffLen == SHA256_BLOCK_SIZE) {
00154             #ifdef LITTLE_ENDIAN_ORDER
00155                 ByteReverseBytes(local, local, SHA256_BLOCK_SIZE);
00156             #endif
00157             Transform(sha256);
00158             AddLength(sha256, SHA256_BLOCK_SIZE);
00159             sha256->buffLen = 0;
00160         }
00161     }
00162 }
00163 
00164 
00165 void Sha256Final(Sha256* sha256, byte* hash)
00166 {
00167     byte* local = (byte*)sha256->buffer;
00168 
00169     AddLength(sha256, sha256->buffLen);  /* before adding pads */
00170 
00171     local[sha256->buffLen++] = 0x80;  /* add 1 */
00172 
00173     /* pad with zeros */
00174     if (sha256->buffLen > SHA256_PAD_SIZE) {
00175         XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen);
00176         sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen;
00177 
00178         #ifdef LITTLE_ENDIAN_ORDER
00179             ByteReverseBytes(local, local, SHA256_BLOCK_SIZE);
00180         #endif
00181         Transform(sha256);
00182         sha256->buffLen = 0;
00183     }
00184     XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen);
00185 
00186     /* put lengths in bits */
00187     sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) +
00188                  (sha256->hiLen << 3);
00189     sha256->loLen = sha256->loLen << 3;
00190 
00191     /* store lengths */
00192     #ifdef LITTLE_ENDIAN_ORDER
00193         ByteReverseBytes(local, local, SHA256_BLOCK_SIZE);
00194     #endif
00195     /* ! length ordering dependent on digest endian type ! */
00196     XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
00197     XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
00198             sizeof(word32));
00199 
00200     Transform(sha256);
00201     #ifdef LITTLE_ENDIAN_ORDER
00202         ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE);
00203     #endif
00204     XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE);
00205 
00206     InitSha256(sha256);  /* reset state */
00207 }
00208 
00209 
00210 #endif /* NO_SHA256 */
00211