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