wolf SSL / CyaSSL

Dependents:   HTTPClient-SSL HTTPClient HTTPClient-SSL http_access ... more

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-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 
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 #if !defined(NO_SHA256)
00032 
00033 #ifdef CYASSL_PIC32MZ_HASH
00034 #define InitSha256   InitSha256_sw
00035 #define Sha256Update Sha256Update_sw
00036 #define Sha256Final  Sha256Final_sw
00037 #endif
00038 
00039 #ifdef HAVE_FIPS
00040     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
00041     #define FIPS_NO_WRAPPERS
00042 #endif
00043 
00044 #include <cyassl/ctaocrypt/sha256.h>
00045 #include <cyassl/ctaocrypt/error-crypt.h>
00046 #ifdef NO_INLINE
00047     #include <cyassl/ctaocrypt/misc.h>
00048 #else
00049     #include <ctaocrypt/src/misc.c>
00050 #endif
00051 
00052 #ifdef FREESCALE_MMCAU
00053     #include "cau_api.h"
00054 #endif
00055 
00056 #ifndef min
00057 
00058     static INLINE word32 min(word32 a, word32 b)
00059     {
00060         return a > b ? b : a;
00061     }
00062 
00063 #endif /* min */
00064 
00065 
00066 int InitSha256(Sha256* sha256)
00067 {
00068     #ifdef FREESCALE_MMCAU
00069         cau_sha256_initialize_output(sha256->digest);
00070     #else
00071         sha256->digest[0] = 0x6A09E667L;
00072         sha256->digest[1] = 0xBB67AE85L;
00073         sha256->digest[2] = 0x3C6EF372L;
00074         sha256->digest[3] = 0xA54FF53AL;
00075         sha256->digest[4] = 0x510E527FL;
00076         sha256->digest[5] = 0x9B05688CL;
00077         sha256->digest[6] = 0x1F83D9ABL;
00078         sha256->digest[7] = 0x5BE0CD19L;
00079     #endif
00080 
00081     sha256->buffLen = 0;
00082     sha256->loLen   = 0;
00083     sha256->hiLen   = 0;
00084 
00085     return 0;
00086 }
00087 
00088 #ifdef FREESCALE_MMCAU
00089     #define XTRANSFORM(S,B)  Transform((S), (B))
00090 
00091 static int Transform(Sha256* sha256, byte* buf)
00092 {
00093     cau_sha256_hash_n(buf, 1, sha256->digest);
00094 
00095     return 0;
00096 }
00097 
00098 #else
00099     #define XTRANSFORM(S,B)  Transform((S))
00100 
00101 static const word32 K[64] = {
00102     0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
00103     0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
00104     0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,
00105     0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
00106     0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,
00107     0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,
00108     0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,
00109     0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
00110     0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,
00111     0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,
00112     0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,
00113     0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
00114     0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
00115 };
00116 
00117 #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
00118 #define Maj(x,y,z)      (((x | y) & z) | (x & y))
00119 #define S(x, n)         rotrFixed(x, n)
00120 #define R(x, n)         (((x)&0xFFFFFFFFU)>>(n))
00121 #define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
00122 #define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
00123 #define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
00124 #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
00125 
00126 #define RND(a,b,c,d,e,f,g,h,i) \
00127      t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
00128      t1 = Sigma0(a) + Maj(a, b, c); \
00129      d += t0; \
00130      h  = t0 + t1;
00131 
00132 
00133 static int Transform(Sha256* sha256)
00134 {
00135     word32 S[8], t0, t1;
00136     int i;
00137 
00138 #ifdef CYASSL_SMALL_STACK
00139     word32* W;
00140 
00141     W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00142     if (W == NULL)
00143         return MEMORY_E;
00144 #else
00145     word32 W[64];
00146 #endif
00147 
00148     /* Copy context->state[] to working vars */
00149     for (i = 0; i < 8; i++)
00150         S[i] = sha256->digest[i];
00151 
00152     for (i = 0; i < 16; i++)
00153         W[i] = sha256->buffer[i];
00154 
00155     for (i = 16; i < 64; i++)
00156         W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];
00157 
00158     for (i = 0; i < 64; i += 8) {
00159         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
00160         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
00161         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
00162         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
00163         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
00164         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
00165         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
00166         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
00167     }
00168 
00169     /* Add the working vars back into digest state[] */
00170     for (i = 0; i < 8; i++) {
00171         sha256->digest[i] += S[i];
00172     }
00173 
00174 #ifdef CYASSL_SMALL_STACK
00175     XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00176 #endif
00177 
00178     return 0;
00179 }
00180 
00181 #endif /* FREESCALE_MMCAU */
00182 
00183 
00184 static INLINE void AddLength(Sha256* sha256, word32 len)
00185 {
00186     word32 tmp = sha256->loLen;
00187     if ( (sha256->loLen += len) < tmp)
00188         sha256->hiLen++;                       /* carry low to high */
00189 }
00190 
00191 
00192 int Sha256Update(Sha256* sha256, const byte* data, word32 len)
00193 {
00194     /* do block size increments */
00195     byte* local = (byte*)sha256->buffer;
00196 
00197     while (len) {
00198         word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen);
00199         XMEMCPY(&local[sha256->buffLen], data, add);
00200 
00201         sha256->buffLen += add;
00202         data            += add;
00203         len             -= add;
00204 
00205         if (sha256->buffLen == SHA256_BLOCK_SIZE) {
00206             int ret;
00207 
00208             #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
00209                 ByteReverseWords(sha256->buffer, sha256->buffer,
00210                                  SHA256_BLOCK_SIZE);
00211             #endif
00212 
00213             ret = XTRANSFORM(sha256, local);
00214             if (ret != 0)
00215                 return ret;
00216 
00217             AddLength(sha256, SHA256_BLOCK_SIZE);
00218             sha256->buffLen = 0;
00219         }
00220     }
00221 
00222     return 0;
00223 }
00224 
00225 
00226 int Sha256Final(Sha256* sha256, byte* hash)
00227 {
00228     byte* local = (byte*)sha256->buffer;
00229     int ret;
00230 
00231     AddLength(sha256, sha256->buffLen);  /* before adding pads */
00232 
00233     local[sha256->buffLen++] = 0x80;     /* add 1 */
00234 
00235     /* pad with zeros */
00236     if (sha256->buffLen > SHA256_PAD_SIZE) {
00237         XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen);
00238         sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen;
00239 
00240         #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
00241             ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE);
00242         #endif
00243 
00244         ret = XTRANSFORM(sha256, local);
00245         if (ret != 0)
00246             return ret;
00247 
00248         sha256->buffLen = 0;
00249     }
00250     XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen);
00251 
00252     /* put lengths in bits */
00253     sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) +
00254                  (sha256->hiLen << 3);
00255     sha256->loLen = sha256->loLen << 3;
00256 
00257     /* store lengths */
00258     #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
00259         ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE);
00260     #endif
00261     /* ! length ordering dependent on digest endian type ! */
00262     XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
00263     XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
00264             sizeof(word32));
00265 
00266     #ifdef FREESCALE_MMCAU
00267         /* Kinetis requires only these bytes reversed */
00268         ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)],
00269                          &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)],
00270                          2 * sizeof(word32));
00271     #endif
00272 
00273     ret = XTRANSFORM(sha256, local);
00274     if (ret != 0)
00275         return ret;
00276 
00277     #ifdef LITTLE_ENDIAN_ORDER
00278         ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE);
00279     #endif
00280     XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE);
00281 
00282     return InitSha256(sha256);  /* reset state */
00283 }
00284 
00285 
00286 #endif /* NO_SHA256 */
00287 
00288