CyaSSL is an SSL library for devices like mbed.
Dependents: cyassl-client Sync
sha.c
00001 /* sha.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 00023 #include "ctc_sha.h" 00024 #ifdef NO_INLINE 00025 #include "misc.h" 00026 #else 00027 #include "misc.c" 00028 #endif 00029 00030 00031 #ifndef min 00032 00033 static INLINE word32 min(word32 a, word32 b) 00034 { 00035 return a > b ? b : a; 00036 } 00037 00038 #endif /* min */ 00039 00040 00041 void InitSha(Sha* sha) 00042 { 00043 sha->digest[0] = 0x67452301L; 00044 sha->digest[1] = 0xEFCDAB89L; 00045 sha->digest[2] = 0x98BADCFEL; 00046 sha->digest[3] = 0x10325476L; 00047 sha->digest[4] = 0xC3D2E1F0L; 00048 00049 sha->buffLen = 0; 00050 sha->loLen = 0; 00051 sha->hiLen = 0; 00052 } 00053 00054 #define blk0(i) (W[i] = sha->buffer[i]) 00055 #define blk1(i) (W[i&15] = \ 00056 rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1)) 00057 00058 #define f1(x,y,z) (z^(x &(y^z))) 00059 #define f2(x,y,z) (x^y^z) 00060 #define f3(x,y,z) ((x&y)|(z&(x|y))) 00061 #define f4(x,y,z) (x^y^z) 00062 00063 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 00064 #define R0(v,w,x,y,z,i) z+= f1(w,x,y) + blk0(i) + 0x5A827999+ \ 00065 rotlFixed(v,5); w = rotlFixed(w,30); 00066 #define R1(v,w,x,y,z,i) z+= f1(w,x,y) + blk1(i) + 0x5A827999+ \ 00067 rotlFixed(v,5); w = rotlFixed(w,30); 00068 #define R2(v,w,x,y,z,i) z+= f2(w,x,y) + blk1(i) + 0x6ED9EBA1+ \ 00069 rotlFixed(v,5); w = rotlFixed(w,30); 00070 #define R3(v,w,x,y,z,i) z+= f3(w,x,y) + blk1(i) + 0x8F1BBCDC+ \ 00071 rotlFixed(v,5); w = rotlFixed(w,30); 00072 #define R4(v,w,x,y,z,i) z+= f4(w,x,y) + blk1(i) + 0xCA62C1D6+ \ 00073 rotlFixed(v,5); w = rotlFixed(w,30); 00074 00075 00076 static void Transform(Sha* sha) 00077 { 00078 word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; 00079 00080 /* Copy context->state[] to working vars */ 00081 word32 a = sha->digest[0]; 00082 word32 b = sha->digest[1]; 00083 word32 c = sha->digest[2]; 00084 word32 d = sha->digest[3]; 00085 word32 e = sha->digest[4]; 00086 00087 /* nearly 1 K bigger in code size but 25% faster */ 00088 /* 4 rounds of 20 operations each. Loop unrolled. */ 00089 R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); 00090 R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); 00091 R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 00092 R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); 00093 00094 R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 00095 00096 R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 00097 R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 00098 R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 00099 R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 00100 R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 00101 00102 R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 00103 R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 00104 R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 00105 R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 00106 R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 00107 00108 R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 00109 R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 00110 R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 00111 R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 00112 R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 00113 00114 /* Add the working vars back into digest state[] */ 00115 sha->digest[0] += a; 00116 sha->digest[1] += b; 00117 sha->digest[2] += c; 00118 sha->digest[3] += d; 00119 sha->digest[4] += e; 00120 } 00121 00122 00123 static INLINE void AddLength(Sha* sha, word32 len) 00124 { 00125 word32 tmp = sha->loLen; 00126 if ( (sha->loLen += len) < tmp) 00127 sha->hiLen++; /* carry low to high */ 00128 } 00129 00130 00131 void ShaUpdate(Sha* sha, const byte* data, word32 len) 00132 { 00133 /* do block size increments */ 00134 byte* local = (byte*)sha->buffer; 00135 00136 while (len) { 00137 word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); 00138 XMEMCPY(&local[sha->buffLen], data, add); 00139 00140 sha->buffLen += add; 00141 data += add; 00142 len -= add; 00143 00144 if (sha->buffLen == SHA_BLOCK_SIZE) { 00145 #ifdef LITTLE_ENDIAN_ORDER 00146 ByteReverseBytes(local, local, SHA_BLOCK_SIZE); 00147 #endif 00148 Transform(sha); 00149 AddLength(sha, SHA_BLOCK_SIZE); 00150 sha->buffLen = 0; 00151 } 00152 } 00153 } 00154 00155 00156 void ShaFinal(Sha* sha, byte* hash) 00157 { 00158 byte* local = (byte*)sha->buffer; 00159 00160 AddLength(sha, sha->buffLen); /* before adding pads */ 00161 00162 local[sha->buffLen++] = 0x80; /* add 1 */ 00163 00164 /* pad with zeros */ 00165 if (sha->buffLen > SHA_PAD_SIZE) { 00166 XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); 00167 sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; 00168 00169 #ifdef LITTLE_ENDIAN_ORDER 00170 ByteReverseBytes(local, local, SHA_BLOCK_SIZE); 00171 #endif 00172 Transform(sha); 00173 sha->buffLen = 0; 00174 } 00175 XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); 00176 00177 /* put lengths in bits */ 00178 sha->loLen = sha->loLen << 3; 00179 sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + 00180 (sha->hiLen << 3); 00181 00182 /* store lengths */ 00183 #ifdef LITTLE_ENDIAN_ORDER 00184 ByteReverseBytes(local, local, SHA_BLOCK_SIZE); 00185 #endif 00186 /* ! length ordering dependent on digest endian type ! */ 00187 XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); 00188 XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); 00189 00190 Transform(sha); 00191 #ifdef LITTLE_ENDIAN_ORDER 00192 ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); 00193 #endif 00194 XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); 00195 00196 InitSha(sha); /* reset state */ 00197 } 00198
Generated on Tue Jul 12 2022 18:43:19 by 1.7.2