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 wolfSSL by
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 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfssl/wolfcrypt/settings.h> 00028 00029 #if !defined(NO_SHA) 00030 00031 #include <wolfssl/wolfcrypt/sha.h> 00032 #include <wolfssl/wolfcrypt/error-crypt.h> 00033 00034 /* fips wrapper calls, user can call direct */ 00035 #ifdef HAVE_FIPS 00036 int wc_InitSha(Sha* sha) 00037 { 00038 return InitSha_fips(sha); 00039 } 00040 int wc_InitSha_ex(Sha* sha, void* heap, int devId) 00041 { 00042 (void)heap; 00043 (void)devId; 00044 return InitSha_fips(sha); 00045 } 00046 00047 int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) 00048 { 00049 return ShaUpdate_fips(sha, data, len); 00050 } 00051 00052 int wc_ShaFinal(Sha* sha, byte* out) 00053 { 00054 return ShaFinal_fips(sha,out); 00055 } 00056 void wc_ShaFree(Sha* sha) 00057 { 00058 (void)sha; 00059 /* Not supported in FIPS */ 00060 } 00061 00062 #else /* else build without fips */ 00063 00064 00065 #if defined(WOLFSSL_TI_HASH) 00066 /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */ 00067 00068 #else 00069 00070 #include <wolfssl/wolfcrypt/logging.h> 00071 #ifdef NO_INLINE 00072 #include <wolfssl/wolfcrypt/misc.h> 00073 #else 00074 #define WOLFSSL_MISC_INCLUDED 00075 #include <wolfcrypt/src/misc.c> 00076 #endif 00077 00078 00079 /* Hardware Acceleration */ 00080 #if defined(WOLFSSL_PIC32MZ_HASH) 00081 #define USE_SHA_SOFTWARE_IMPL 00082 #define wc_InitSha wc_InitSha_sw 00083 #define wc_ShaUpdate wc_ShaUpdate_sw 00084 #define wc_ShaFinal wc_ShaFinal_sw 00085 00086 #elif defined(STM32F2_HASH) || defined(STM32F4_HASH) 00087 00088 /* 00089 * STM32F2/F4 hardware SHA1 support through the standard peripheral 00090 * library. (See note in README). 00091 */ 00092 00093 static int InitSha(Sha* sha) 00094 { 00095 /* STM32 struct notes: 00096 * sha->buffer = first 4 bytes used to hold partial block if needed 00097 * sha->buffLen = num bytes currently stored in sha->buffer 00098 * sha->loLen = num bytes that have been written to STM32 FIFO 00099 */ 00100 XMEMSET(sha->buffer, 0, SHA_REG_SIZE); 00101 sha->buffLen = 0; 00102 sha->loLen = 0; 00103 00104 /* initialize HASH peripheral */ 00105 HASH_DeInit(); 00106 00107 /* configure algo used, algo mode, datatype */ 00108 HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); 00109 HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH 00110 | HASH_DataType_8b); 00111 00112 /* reset HASH processor */ 00113 HASH->CR |= HASH_CR_INIT; 00114 00115 return 0; 00116 } 00117 00118 int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) 00119 { 00120 word32 i = 0; 00121 word32 fill = 0; 00122 word32 diff = 0; 00123 00124 /* if saved partial block is available */ 00125 if (sha->buffLen) { 00126 fill = 4 - sha->buffLen; 00127 00128 /* if enough data to fill, fill and push to FIFO */ 00129 if (fill <= len) { 00130 XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); 00131 HASH_DataIn(*(uint32_t*)sha->buffer); 00132 00133 data += fill; 00134 len -= fill; 00135 sha->loLen += 4; 00136 sha->buffLen = 0; 00137 } else { 00138 /* append partial to existing stored block */ 00139 XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); 00140 sha->buffLen += len; 00141 return 0; 00142 } 00143 } 00144 00145 /* write input block in the IN FIFO */ 00146 for(i = 0; i < len; i += 4) 00147 { 00148 diff = len - i; 00149 if ( diff < 4) { 00150 /* store incomplete last block, not yet in FIFO */ 00151 XMEMSET(sha->buffer, 0, SHA_REG_SIZE); 00152 XMEMCPY((byte*)sha->buffer, data, diff); 00153 sha->buffLen = diff; 00154 } else { 00155 HASH_DataIn(*(uint32_t*)data); 00156 data+=4; 00157 } 00158 } 00159 00160 /* keep track of total data length thus far */ 00161 sha->loLen += (len - sha->buffLen); 00162 00163 return 0; 00164 } 00165 00166 int wc_ShaFinal(Sha* sha, byte* hash) 00167 { 00168 __IO uint16_t nbvalidbitsdata = 0; 00169 00170 /* finish reading any trailing bytes into FIFO */ 00171 if (sha->buffLen) { 00172 HASH_DataIn(*(uint32_t*)sha->buffer); 00173 sha->loLen += sha->buffLen; 00174 } 00175 00176 /* calculate number of valid bits in last word of input data */ 00177 nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE); 00178 00179 /* configure number of valid bits in last word of the data */ 00180 HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); 00181 00182 /* start HASH processor */ 00183 HASH_StartDigest(); 00184 00185 /* wait until Busy flag == RESET */ 00186 while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} 00187 00188 /* read message digest */ 00189 sha->digest[0] = HASH->HR[0]; 00190 sha->digest[1] = HASH->HR[1]; 00191 sha->digest[2] = HASH->HR[2]; 00192 sha->digest[3] = HASH->HR[3]; 00193 sha->digest[4] = HASH->HR[4]; 00194 00195 ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); 00196 00197 XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); 00198 00199 return wc_InitSha(sha); /* reset state */ 00200 } 00201 00202 00203 #elif defined(FREESCALE_LTC_SHA) 00204 00205 #include "fsl_ltc.h" 00206 static int InitSha(Sha* sha) 00207 { 00208 LTC_HASH_Init(LTC_BASE, &sha->ctx, kLTC_Sha1, NULL, 0); 00209 return 0; 00210 } 00211 00212 int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) 00213 { 00214 LTC_HASH_Update(&sha->ctx, data, len); 00215 return 0; 00216 } 00217 00218 int wc_ShaFinal(Sha* sha, byte* hash) 00219 { 00220 uint32_t hashlen = SHA_DIGEST_SIZE; 00221 LTC_HASH_Finish(&sha->ctx, hash, &hashlen); 00222 return wc_InitSha(sha); /* reset state */ 00223 } 00224 00225 00226 #elif defined(FREESCALE_MMCAU_SHA) 00227 00228 #include "fsl_mmcau.h" 00229 #define USE_SHA_SOFTWARE_IMPL /* Only for API's, actual transform is here */ 00230 #define XSHATRANSFORM ShaTransform 00231 00232 static int InitSha(Sha* sha) 00233 { 00234 int ret = 0; 00235 ret = wolfSSL_CryptHwMutexLock(); 00236 if(ret != 0) { 00237 return ret; 00238 } 00239 MMCAU_SHA1_InitializeOutput((uint32_t*)sha->digest); 00240 wolfSSL_CryptHwMutexUnLock(); 00241 00242 sha->buffLen = 0; 00243 sha->loLen = 0; 00244 sha->hiLen = 0; 00245 00246 return ret; 00247 } 00248 00249 static int ShaTransform(Sha* sha, byte* data) 00250 { 00251 int ret = wolfSSL_CryptHwMutexLock(); 00252 if(ret == 0) { 00253 MMCAU_SHA1_HashN(data, 1, (uint32_t*)sha->digest); 00254 wolfSSL_CryptHwMutexUnLock(); 00255 } 00256 return ret; 00257 } 00258 00259 #else 00260 00261 /* Software implementation */ 00262 #define USE_SHA_SOFTWARE_IMPL 00263 00264 static int InitSha(Sha* sha) 00265 { 00266 int ret = 0; 00267 00268 sha->digest[0] = 0x67452301L; 00269 sha->digest[1] = 0xEFCDAB89L; 00270 sha->digest[2] = 0x98BADCFEL; 00271 sha->digest[3] = 0x10325476L; 00272 sha->digest[4] = 0xC3D2E1F0L; 00273 00274 sha->buffLen = 0; 00275 sha->loLen = 0; 00276 sha->hiLen = 0; 00277 00278 return ret; 00279 } 00280 00281 #endif /* End Hardware Acceleration */ 00282 00283 00284 /* Software implementation */ 00285 #ifdef USE_SHA_SOFTWARE_IMPL 00286 00287 /* Check if custom Sha transform is used */ 00288 #ifndef XSHATRANSFORM 00289 #define XSHATRANSFORM ShaTransform 00290 00291 #define blk0(i) (W[i] = sha->buffer[i]) 00292 #define blk1(i) (W[(i)&15] = \ 00293 rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1)) 00294 00295 #define f1(x,y,z) ((z)^((x) &((y)^(z)))) 00296 #define f2(x,y,z) ((x)^(y)^(z)) 00297 #define f3(x,y,z) (((x)&(y))|((z)&((x)|(y)))) 00298 #define f4(x,y,z) ((x)^(y)^(z)) 00299 00300 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 00301 #define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \ 00302 rotlFixed((v),5); (w) = rotlFixed((w),30); 00303 #define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \ 00304 rotlFixed((v),5); (w) = rotlFixed((w),30); 00305 #define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \ 00306 rotlFixed((v),5); (w) = rotlFixed((w),30); 00307 #define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \ 00308 rotlFixed((v),5); (w) = rotlFixed((w),30); 00309 #define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \ 00310 rotlFixed((v),5); (w) = rotlFixed((w),30); 00311 00312 static void ShaTransform(Sha* sha, byte* data) 00313 { 00314 word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; 00315 00316 /* Copy context->state[] to working vars */ 00317 word32 a = sha->digest[0]; 00318 word32 b = sha->digest[1]; 00319 word32 c = sha->digest[2]; 00320 word32 d = sha->digest[3]; 00321 word32 e = sha->digest[4]; 00322 00323 #ifdef USE_SLOW_SHA 00324 word32 t, i; 00325 00326 for (i = 0; i < 16; i++) { 00327 R0(a, b, c, d, e, i); 00328 t = e; e = d; d = c; c = b; b = a; a = t; 00329 } 00330 00331 for (; i < 20; i++) { 00332 R1(a, b, c, d, e, i); 00333 t = e; e = d; d = c; c = b; b = a; a = t; 00334 } 00335 00336 for (; i < 40; i++) { 00337 R2(a, b, c, d, e, i); 00338 t = e; e = d; d = c; c = b; b = a; a = t; 00339 } 00340 00341 for (; i < 60; i++) { 00342 R3(a, b, c, d, e, i); 00343 t = e; e = d; d = c; c = b; b = a; a = t; 00344 } 00345 00346 for (; i < 80; i++) { 00347 R4(a, b, c, d, e, i); 00348 t = e; e = d; d = c; c = b; b = a; a = t; 00349 } 00350 #else 00351 /* nearly 1 K bigger in code size but 25% faster */ 00352 /* 4 rounds of 20 operations each. Loop unrolled. */ 00353 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); 00354 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); 00355 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); 00356 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); 00357 00358 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); 00359 00360 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); 00361 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); 00362 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); 00363 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); 00364 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); 00365 00366 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); 00367 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); 00368 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); 00369 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); 00370 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); 00371 00372 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); 00373 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); 00374 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); 00375 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); 00376 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); 00377 #endif 00378 00379 /* Add the working vars back into digest state[] */ 00380 sha->digest[0] += a; 00381 sha->digest[1] += b; 00382 sha->digest[2] += c; 00383 sha->digest[3] += d; 00384 sha->digest[4] += e; 00385 00386 (void)data; /* Not used */ 00387 } 00388 #endif /* !USE_CUSTOM_SHA_TRANSFORM */ 00389 00390 00391 static INLINE void AddLength(Sha* sha, word32 len) 00392 { 00393 word32 tmp = sha->loLen; 00394 if ( (sha->loLen += len) < tmp) 00395 sha->hiLen++; /* carry low to high */ 00396 } 00397 00398 int wc_InitSha_ex(Sha* sha, void* heap, int devId) 00399 { 00400 int ret = 0; 00401 00402 if (sha == NULL) 00403 return BAD_FUNC_ARG; 00404 00405 sha->heap = heap; 00406 00407 ret = InitSha(sha); 00408 if (ret != 0) 00409 return ret; 00410 00411 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) 00412 ret = wolfAsync_DevCtxInit(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA, 00413 sha->heap, devId); 00414 #else 00415 (void)devId; 00416 #endif /* WOLFSSL_ASYNC_CRYPT */ 00417 00418 return ret; 00419 } 00420 00421 int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) 00422 { 00423 /* do block size increments */ 00424 byte* local = (byte*)sha->buffer; 00425 00426 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) 00427 if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) { 00428 #if defined(HAVE_INTEL_QA) 00429 return IntelQaSymSha(&sha->asyncDev, NULL, data, len); 00430 #endif 00431 } 00432 #endif /* WOLFSSL_ASYNC_CRYPT */ 00433 00434 /* check that internal buffLen is valid */ 00435 if (sha->buffLen >= SHA_BLOCK_SIZE) 00436 return BUFFER_E; 00437 00438 while (len) { 00439 word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); 00440 XMEMCPY(&local[sha->buffLen], data, add); 00441 00442 sha->buffLen += add; 00443 data += add; 00444 len -= add; 00445 00446 if (sha->buffLen == SHA_BLOCK_SIZE) { 00447 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) 00448 ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); 00449 #endif 00450 XSHATRANSFORM(sha, local); 00451 AddLength(sha, SHA_BLOCK_SIZE); 00452 sha->buffLen = 0; 00453 } 00454 } 00455 00456 return 0; 00457 } 00458 00459 int wc_ShaFinal(Sha* sha, byte* hash) 00460 { 00461 byte* local = (byte*)sha->buffer; 00462 00463 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) 00464 if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) { 00465 #if defined(HAVE_INTEL_QA) 00466 return IntelQaSymSha(&sha->asyncDev, hash, NULL, SHA_DIGEST_SIZE); 00467 #endif 00468 } 00469 #endif /* WOLFSSL_ASYNC_CRYPT */ 00470 00471 AddLength(sha, sha->buffLen); /* before adding pads */ 00472 00473 local[sha->buffLen++] = 0x80; /* add 1 */ 00474 00475 /* pad with zeros */ 00476 if (sha->buffLen > SHA_PAD_SIZE) { 00477 XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); 00478 sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; 00479 00480 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) 00481 ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); 00482 #endif 00483 XSHATRANSFORM(sha, local); 00484 sha->buffLen = 0; 00485 } 00486 XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); 00487 00488 /* put lengths in bits */ 00489 sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + 00490 (sha->hiLen << 3); 00491 sha->loLen = sha->loLen << 3; 00492 00493 /* store lengths */ 00494 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) 00495 ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); 00496 #endif 00497 /* ! length ordering dependent on digest endian type ! */ 00498 XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); 00499 XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); 00500 00501 #ifdef FREESCALE_MMCAU_SHA 00502 /* Kinetis requires only these bytes reversed */ 00503 ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)], 00504 &sha->buffer[SHA_PAD_SIZE/sizeof(word32)], 00505 2 * sizeof(word32)); 00506 #endif 00507 00508 XSHATRANSFORM(sha, local); 00509 #ifdef LITTLE_ENDIAN_ORDER 00510 ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); 00511 #endif 00512 XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); 00513 00514 return InitSha(sha); /* reset state */ 00515 } 00516 00517 #endif /* USE_SHA_SOFTWARE_IMPL */ 00518 00519 00520 int wc_InitSha(Sha* sha) 00521 { 00522 return wc_InitSha_ex(sha, NULL, INVALID_DEVID); 00523 } 00524 00525 void wc_ShaFree(Sha* sha) 00526 { 00527 if (sha == NULL) 00528 return; 00529 00530 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) 00531 wolfAsync_DevCtxFree(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA); 00532 #endif /* WOLFSSL_ASYNC_CRYPT */ 00533 } 00534 00535 #endif /* !WOLFSSL_TI_HASH */ 00536 #endif /* HAVE_FIPS */ 00537 00538 #ifndef WOLFSSL_TI_HASH 00539 int wc_ShaGetHash(Sha* sha, byte* hash) 00540 { 00541 int ret; 00542 Sha tmpSha; 00543 00544 if (sha == NULL || hash == NULL) 00545 return BAD_FUNC_ARG; 00546 00547 ret = wc_ShaCopy(sha, &tmpSha); 00548 if (ret == 0) { 00549 ret = wc_ShaFinal(&tmpSha, hash); 00550 } 00551 return ret; 00552 } 00553 00554 int wc_ShaCopy(Sha* src, Sha* dst) 00555 { 00556 int ret = 0; 00557 00558 if (src == NULL || dst == NULL) 00559 return BAD_FUNC_ARG; 00560 00561 XMEMCPY(dst, src, sizeof(Sha)); 00562 00563 #ifdef WOLFSSL_ASYNC_CRYPT 00564 ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); 00565 #endif 00566 00567 return ret; 00568 } 00569 #endif /* !WOLFSSL_TI_HASH */ 00570 00571 #endif /* !NO_SHA */ 00572
Generated on Tue Jul 12 2022 23:30:59 by
1.7.2
