MultiTech / CyaSSL

Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

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