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.
sha.c
00001 /* sha.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 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <cyassl/ctaocrypt/settings.h> 00028 00029 #if !defined(NO_SHA) 00030 00031 #ifdef CYASSL_PIC32MZ_HASH 00032 #define InitSha InitSha_sw 00033 #define ShaUpdate ShaUpdate_sw 00034 #define ShaFinal ShaFinal_sw 00035 #endif 00036 00037 #ifdef HAVE_FIPS 00038 /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ 00039 #define FIPS_NO_WRAPPERS 00040 #endif 00041 00042 #include <cyassl/ctaocrypt/sha.h> 00043 #ifdef NO_INLINE 00044 #include <cyassl/ctaocrypt/misc.h> 00045 #else 00046 #include <ctaocrypt/src/misc.c> 00047 #endif 00048 00049 #ifdef FREESCALE_MMCAU 00050 #include "cau_api.h" 00051 #define XTRANSFORM(S,B) cau_sha1_hash_n((B), 1, ((S))->digest) 00052 #else 00053 #define XTRANSFORM(S,B) Transform((S)) 00054 #endif 00055 00056 00057 #ifdef STM32F2_HASH 00058 /* 00059 * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral 00060 * library. Documentation located in STM32F2xx Standard Peripheral Library 00061 * document (See note in README). 00062 */ 00063 #include "stm32f2xx.h" 00064 #include "stm32f2xx_hash.h" 00065 00066 int InitSha(Sha* sha) 00067 { 00068 /* STM32F2 struct notes: 00069 * sha->buffer = first 4 bytes used to hold partial block if needed 00070 * sha->buffLen = num bytes currently stored in sha->buffer 00071 * sha->loLen = num bytes that have been written to STM32 FIFO 00072 */ 00073 XMEMSET(sha->buffer, 0, SHA_REG_SIZE); 00074 sha->buffLen = 0; 00075 sha->loLen = 0; 00076 00077 /* initialize HASH peripheral */ 00078 HASH_DeInit(); 00079 00080 /* configure algo used, algo mode, datatype */ 00081 HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); 00082 HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH 00083 | HASH_DataType_8b); 00084 00085 /* reset HASH processor */ 00086 HASH->CR |= HASH_CR_INIT; 00087 00088 return 0; 00089 } 00090 00091 int ShaUpdate(Sha* sha, const byte* data, word32 len) 00092 { 00093 word32 i = 0; 00094 word32 fill = 0; 00095 word32 diff = 0; 00096 00097 /* if saved partial block is available */ 00098 if (sha->buffLen) { 00099 fill = 4 - sha->buffLen; 00100 00101 /* if enough data to fill, fill and push to FIFO */ 00102 if (fill <= len) { 00103 XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); 00104 HASH_DataIn(*(uint32_t*)sha->buffer); 00105 00106 data += fill; 00107 len -= fill; 00108 sha->loLen += 4; 00109 sha->buffLen = 0; 00110 } else { 00111 /* append partial to existing stored block */ 00112 XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); 00113 sha->buffLen += len; 00114 return; 00115 } 00116 } 00117 00118 /* write input block in the IN FIFO */ 00119 for(i = 0; i < len; i += 4) 00120 { 00121 diff = len - i; 00122 if ( diff < 4) { 00123 /* store incomplete last block, not yet in FIFO */ 00124 XMEMSET(sha->buffer, 0, SHA_REG_SIZE); 00125 XMEMCPY((byte*)sha->buffer, data, diff); 00126 sha->buffLen = diff; 00127 } else { 00128 HASH_DataIn(*(uint32_t*)data); 00129 data+=4; 00130 } 00131 } 00132 00133 /* keep track of total data length thus far */ 00134 sha->loLen += (len - sha->buffLen); 00135 00136 return 0; 00137 } 00138 00139 int ShaFinal(Sha* sha, byte* hash) 00140 { 00141 __IO uint16_t nbvalidbitsdata = 0; 00142 00143 /* finish reading any trailing bytes into FIFO */ 00144 if (sha->buffLen) { 00145 HASH_DataIn(*(uint32_t*)sha->buffer); 00146 sha->loLen += sha->buffLen; 00147 } 00148 00149 /* calculate number of valid bits in last word of input data */ 00150 nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE); 00151 00152 /* configure number of valid bits in last word of the data */ 00153 HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); 00154 00155 /* start HASH processor */ 00156 HASH_StartDigest(); 00157 00158 /* wait until Busy flag == RESET */ 00159 while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} 00160 00161 /* read message digest */ 00162 sha->digest[0] = HASH->HR[0]; 00163 sha->digest[1] = HASH->HR[1]; 00164 sha->digest[2] = HASH->HR[2]; 00165 sha->digest[3] = HASH->HR[3]; 00166 sha->digest[4] = HASH->HR[4]; 00167 00168 ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); 00169 00170 XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); 00171 00172 return InitSha(sha); /* reset state */ 00173 } 00174 00175 #else /* CTaoCrypt software implementation */ 00176 00177 #ifndef min 00178 00179 static INLINE word32 min(word32 a, word32 b) 00180 { 00181 return a > b ? b : a; 00182 } 00183 00184 #endif /* min */ 00185 00186 00187 int InitSha(Sha* sha) 00188 { 00189 #ifdef FREESCALE_MMCAU 00190 cau_sha1_initialize_output(sha->digest); 00191 #else 00192 sha->digest[0] = 0x67452301L; 00193 sha->digest[1] = 0xEFCDAB89L; 00194 sha->digest[2] = 0x98BADCFEL; 00195 sha->digest[3] = 0x10325476L; 00196 sha->digest[4] = 0xC3D2E1F0L; 00197 #endif 00198 00199 sha->buffLen = 0; 00200 sha->loLen = 0; 00201 sha->hiLen = 0; 00202 00203 return 0; 00204 } 00205 00206 #ifndef FREESCALE_MMCAU 00207 00208 #define blk0(i) (W[i] = sha->buffer[i]) 00209 #define blk1(i) (W[i&15] = \ 00210 rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1)) 00211 00212 #define f1(x,y,z) (z^(x &(y^z))) 00213 #define f2(x,y,z) (x^y^z) 00214 #define f3(x,y,z) ((x&y)|(z&(x|y))) 00215 #define f4(x,y,z) (x^y^z) 00216 00217 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 00218 #define R0(v,w,x,y,z,i) z+= f1(w,x,y) + blk0(i) + 0x5A827999+ \ 00219 rotlFixed(v,5); w = rotlFixed(w,30); 00220 #define R1(v,w,x,y,z,i) z+= f1(w,x,y) + blk1(i) + 0x5A827999+ \ 00221 rotlFixed(v,5); w = rotlFixed(w,30); 00222 #define R2(v,w,x,y,z,i) z+= f2(w,x,y) + blk1(i) + 0x6ED9EBA1+ \ 00223 rotlFixed(v,5); w = rotlFixed(w,30); 00224 #define R3(v,w,x,y,z,i) z+= f3(w,x,y) + blk1(i) + 0x8F1BBCDC+ \ 00225 rotlFixed(v,5); w = rotlFixed(w,30); 00226 #define R4(v,w,x,y,z,i) z+= f4(w,x,y) + blk1(i) + 0xCA62C1D6+ \ 00227 rotlFixed(v,5); w = rotlFixed(w,30); 00228 00229 00230 static void Transform(Sha* sha) 00231 { 00232 word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; 00233 00234 /* Copy context->state[] to working vars */ 00235 word32 a = sha->digest[0]; 00236 word32 b = sha->digest[1]; 00237 word32 c = sha->digest[2]; 00238 word32 d = sha->digest[3]; 00239 word32 e = sha->digest[4]; 00240 00241 #ifdef USE_SLOW_SHA 00242 word32 t, i; 00243 00244 for (i = 0; i < 16; i++) { 00245 R0(a, b, c, d, e, i); 00246 t = e; e = d; d = c; c = b; b = a; a = t; 00247 } 00248 00249 for (; i < 20; i++) { 00250 R1(a, b, c, d, e, i); 00251 t = e; e = d; d = c; c = b; b = a; a = t; 00252 } 00253 00254 for (; i < 40; i++) { 00255 R2(a, b, c, d, e, i); 00256 t = e; e = d; d = c; c = b; b = a; a = t; 00257 } 00258 00259 for (; i < 60; i++) { 00260 R3(a, b, c, d, e, i); 00261 t = e; e = d; d = c; c = b; b = a; a = t; 00262 } 00263 00264 for (; i < 80; i++) { 00265 R4(a, b, c, d, e, i); 00266 t = e; e = d; d = c; c = b; b = a; a = t; 00267 } 00268 #else 00269 /* nearly 1 K bigger in code size but 25% faster */ 00270 /* 4 rounds of 20 operations each. Loop unrolled. */ 00271 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); 00272 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); 00273 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); 00274 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); 00275 00276 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); 00277 00278 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); 00279 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); 00280 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); 00281 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); 00282 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); 00283 00284 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); 00285 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); 00286 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); 00287 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); 00288 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); 00289 00290 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); 00291 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); 00292 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); 00293 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); 00294 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); 00295 #endif 00296 00297 /* Add the working vars back into digest state[] */ 00298 sha->digest[0] += a; 00299 sha->digest[1] += b; 00300 sha->digest[2] += c; 00301 sha->digest[3] += d; 00302 sha->digest[4] += e; 00303 } 00304 00305 #endif /* FREESCALE_MMCAU */ 00306 00307 00308 static INLINE void AddLength(Sha* sha, word32 len) 00309 { 00310 word32 tmp = sha->loLen; 00311 if ( (sha->loLen += len) < tmp) 00312 sha->hiLen++; /* carry low to high */ 00313 } 00314 00315 00316 int ShaUpdate(Sha* sha, const byte* data, word32 len) 00317 { 00318 /* do block size increments */ 00319 byte* local = (byte*)sha->buffer; 00320 00321 while (len) { 00322 word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); 00323 XMEMCPY(&local[sha->buffLen], data, add); 00324 00325 sha->buffLen += add; 00326 data += add; 00327 len -= add; 00328 00329 if (sha->buffLen == SHA_BLOCK_SIZE) { 00330 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) 00331 ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); 00332 #endif 00333 XTRANSFORM(sha, local); 00334 AddLength(sha, SHA_BLOCK_SIZE); 00335 sha->buffLen = 0; 00336 } 00337 } 00338 00339 return 0; 00340 } 00341 00342 00343 int ShaFinal(Sha* sha, byte* hash) 00344 { 00345 byte* local = (byte*)sha->buffer; 00346 00347 AddLength(sha, sha->buffLen); /* before adding pads */ 00348 00349 local[sha->buffLen++] = 0x80; /* add 1 */ 00350 00351 /* pad with zeros */ 00352 if (sha->buffLen > SHA_PAD_SIZE) { 00353 XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); 00354 sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; 00355 00356 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) 00357 ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); 00358 #endif 00359 XTRANSFORM(sha, local); 00360 sha->buffLen = 0; 00361 } 00362 XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); 00363 00364 /* put lengths in bits */ 00365 sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + 00366 (sha->hiLen << 3); 00367 sha->loLen = sha->loLen << 3; 00368 00369 /* store lengths */ 00370 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) 00371 ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); 00372 #endif 00373 /* ! length ordering dependent on digest endian type ! */ 00374 XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); 00375 XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); 00376 00377 #ifdef FREESCALE_MMCAU 00378 /* Kinetis requires only these bytes reversed */ 00379 ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)], 00380 &sha->buffer[SHA_PAD_SIZE/sizeof(word32)], 00381 2 * sizeof(word32)); 00382 #endif 00383 00384 XTRANSFORM(sha, local); 00385 #ifdef LITTLE_ENDIAN_ORDER 00386 ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); 00387 #endif 00388 XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); 00389 00390 return InitSha(sha); /* reset state */ 00391 } 00392 00393 #endif /* STM32F2_HASH */ 00394 00395 #endif /* NO_SHA */
Generated on Tue Jul 12 2022 20:12:51 by
