Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of CyaSSL-forEncrypt by
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 Mon Jul 25 2022 10:27:44 by
1.7.2
