3 * Copyright (C) 2006-2014 wolfSSL Inc.
5 * This file is part of CyaSSL.
7 * CyaSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CyaSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 /* code submitted by raphael.huck@efixo.com */
29 #include <cyassl/ctaocrypt/settings.h>
31 #if !defined(NO_SHA256)
33 #ifdef CYASSL_PIC32MZ_HASH
34 #define InitSha256 InitSha256_sw
35 #define Sha256Update Sha256Update_sw
36 #define Sha256Final Sha256Final_sw
40 /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
41 #define FIPS_NO_WRAPPERS
44 #include <cyassl/ctaocrypt/sha256.h>
45 #include <cyassl/ctaocrypt/logging.h>
46 #include <cyassl/ctaocrypt/error-crypt.h>
49 #include <cyassl/ctaocrypt/misc.h>
51 #include <ctaocrypt/src/misc.c>
54 #ifdef FREESCALE_MMCAU
60 static INLINE word32 min(word32 a, word32 b)
68 int InitSha256(Sha256* sha256)
70 #ifdef FREESCALE_MMCAU
71 cau_sha256_initialize_output(sha256->digest);
73 sha256->digest[0] = 0x6A09E667L;
74 sha256->digest[1] = 0xBB67AE85L;
75 sha256->digest[2] = 0x3C6EF372L;
76 sha256->digest[3] = 0xA54FF53AL;
77 sha256->digest[4] = 0x510E527FL;
78 sha256->digest[5] = 0x9B05688CL;
79 sha256->digest[6] = 0x1F83D9ABL;
80 sha256->digest[7] = 0x5BE0CD19L;
90 #ifdef FREESCALE_MMCAU
91 #define XTRANSFORM(S,B) Transform((S), (B))
93 static int Transform(Sha256* sha256, byte* buf)
95 cau_sha256_hash_n(buf, 1, sha256->digest);
101 #define XTRANSFORM(S,B) Transform((S))
103 static const word32 K[64] = {
104 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
105 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
106 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,
107 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
108 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,
109 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,
110 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,
111 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
112 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,
113 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,
114 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,
115 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
116 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
119 #define Ch(x,y,z) (z ^ (x & (y ^ z)))
120 #define Maj(x,y,z) (((x | y) & z) | (x & y))
121 #define S(x, n) rotrFixed(x, n)
122 #define R(x, n) (((x)&0xFFFFFFFFU)>>(n))
123 #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
124 #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
125 #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
126 #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
128 #define RND(a,b,c,d,e,f,g,h,i) \
129 t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
130 t1 = Sigma0(a) + Maj(a, b, c); \
135 static int Transform(Sha256* sha256)
140 #ifdef CYASSL_SMALL_STACK
143 W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER);
150 /* Copy context->state[] to working vars */
151 for (i = 0; i < 8; i++)
152 S[i] = sha256->digest[i];
154 for (i = 0; i < 16; i++)
155 W[i] = sha256->buffer[i];
157 for (i = 16; i < 64; i++)
158 W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];
160 for (i = 0; i < 64; i += 8) {
161 RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
162 RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
163 RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
164 RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
165 RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
166 RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
167 RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
168 RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
171 /* Add the working vars back into digest state[] */
172 for (i = 0; i < 8; i++) {
173 sha256->digest[i] += S[i];
176 #ifdef CYASSL_SMALL_STACK
177 XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
183 #endif /* FREESCALE_MMCAU */
186 static INLINE void AddLength(Sha256* sha256, word32 len)
188 word32 tmp = sha256->loLen;
189 if ( (sha256->loLen += len) < tmp)
190 sha256->hiLen++; /* carry low to high */
194 int Sha256Update(Sha256* sha256, const byte* data, word32 len)
196 /* do block size increments */
197 byte* local = (byte*)sha256->buffer;
200 word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen);
201 XMEMCPY(&local[sha256->buffLen], data, add);
203 sha256->buffLen += add;
207 if (sha256->buffLen == SHA256_BLOCK_SIZE) {
210 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
211 ByteReverseWords(sha256->buffer, sha256->buffer,
215 ret = XTRANSFORM(sha256, local);
219 AddLength(sha256, SHA256_BLOCK_SIZE);
228 int Sha256Final(Sha256* sha256, byte* hash)
230 byte* local = (byte*)sha256->buffer;
233 AddLength(sha256, sha256->buffLen); /* before adding pads */
235 local[sha256->buffLen++] = 0x80; /* add 1 */
238 if (sha256->buffLen > SHA256_PAD_SIZE) {
239 XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen);
240 sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen;
242 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
243 ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE);
246 ret = XTRANSFORM(sha256, local);
252 XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen);
254 /* put lengths in bits */
255 sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) +
256 (sha256->hiLen << 3);
257 sha256->loLen = sha256->loLen << 3;
260 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
261 ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE);
263 /* ! length ordering dependent on digest endian type ! */
264 XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
265 XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
268 #ifdef FREESCALE_MMCAU
269 /* Kinetis requires only these bytes reversed */
270 ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)],
271 &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)],
275 ret = XTRANSFORM(sha256, local);
279 #ifdef LITTLE_ENDIAN_ORDER
280 ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE);
282 XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE);
284 return InitSha256(sha256); /* reset state */
288 int Sha256Hash(const byte* data, word32 len, byte* hash)
291 #ifdef CYASSL_SMALL_STACK
297 #ifdef CYASSL_SMALL_STACK
298 sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER);
303 if ((ret = InitSha256(sha256)) != 0) {
304 CYASSL_MSG("InitSha256 failed");
306 else if ((ret = Sha256Update(sha256, data, len)) != 0) {
307 CYASSL_MSG("Sha256Update failed");
309 else if ((ret = Sha256Final(sha256, hash)) != 0) {
310 CYASSL_MSG("Sha256Final failed");
313 #ifdef CYASSL_SMALL_STACK
314 XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
321 #endif /* NO_SHA256 */