wolf SSL / CyaSSL-2.9.4

Dependents:  

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