ssh lib

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sha.c Source File

sha.c

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