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