diff --git a/.github/workflows/cryptocb-only.yml b/.github/workflows/cryptocb-only.yml index 63400f2f9a..5aedf4c873 100644 --- a/.github/workflows/cryptocb-only.yml +++ b/.github/workflows/cryptocb-only.yml @@ -33,6 +33,19 @@ jobs: # the software path via cryptocb. - name: SHA256 cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA256 + # WOLF_CRYPTO_CB_ONLY_SHA512: strips software SHA-512 family (SHA-384, + # SHA-512/224, SHA-512/256, SHA-512); swdev handles every variant + # explicitly via cryptocb. + - name: SHA512 + cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA512 + # Same as SHA512 but tells swdev to refuse the SHA-384 / SHA-512/224 / + # SHA-512/256 variant callbacks (WOLFSSL_SWDEV_SHA512_GENERAL_ONLY). That + # forces the cryptocb dispatcher's fallback-to-plain-SHA-512-with- + # truncation path. The SHA512 entry above instead has swdev handle + # every variant end-to-end, so the dispatcher fallback is otherwise + # uncovered. + - name: SHA512_via_general + cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA512 -DWOLFSSL_SWDEV_SHA512_GENERAL_ONLY # WOLF_CRYPTO_CB_ONLY_AES: strips software AES; swdev provides the # software path via cryptocb. - name: AES @@ -51,7 +64,8 @@ jobs: - name: ALL cppflags: >- -DWOLF_CRYPTO_CB_ONLY_ECC -DWOLF_CRYPTO_CB_ONLY_RSA - -DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_AES + -DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_SHA512 + -DWOLF_CRYPTO_CB_ONLY_AES name: make check (${{ matrix.name }}) if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} runs-on: ubuntu-24.04 diff --git a/tests/api.c b/tests/api.c index db7f271815..bf6915001c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -30768,7 +30768,8 @@ static int test_SSL_CIPHER_get_xxx(void) #if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ (!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)) + !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA512)) static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer, int* keyFormat) @@ -31772,7 +31773,8 @@ static int test_wc_CryptoCb(void) EXPECT_DECLS; #if defined(WOLF_CRYPTO_CB) && \ (!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)) + !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA512)) /* TODO: Add crypto callback API tests */ #ifdef HAVE_IO_TESTS_DEPENDENCIES diff --git a/tests/api/test_sha512.c b/tests/api/test_sha512.c index 419fb60b31..d23c38e0c8 100644 --- a/tests/api/test_sha512.c +++ b/tests/api/test_sha512.c @@ -874,3 +874,110 @@ int test_wc_Sha384_Flags(void) return EXPECT_RESULT(); } +#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHA384) && \ + defined(WOLFSSL_SHA512) && !defined(NO_SHA2_CRYPTO_CB) + +#include + +#define TEST_CRYPTOCB_SHA384_FALLBACK_DEVID 2 + +typedef struct { + int sha384Seen; + int sha512Seen; +} Sha384FallbackCbCtx; + +static int sha384_fallback_dev_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + Sha384FallbackCbCtx* cbCtx = (Sha384FallbackCbCtx*)ctx; + int i; + + (void)devIdArg; + + if (info == NULL || cbCtx == NULL) + return BAD_FUNC_ARG; + + if (info->algo_type != WC_ALGO_TYPE_HASH) + return CRYPTOCB_UNAVAILABLE; + + if (info->hash.type == WC_HASH_TYPE_SHA384) { + cbCtx->sha384Seen++; + return CRYPTOCB_UNAVAILABLE; + } + + if (info->hash.type == WC_HASH_TYPE_SHA512) { + cbCtx->sha512Seen++; + if (info->hash.digest != NULL) { + for (i = 0; i < WC_SHA512_DIGEST_SIZE; i++) + info->hash.digest[i] = (byte)(0x80 + i); + } + /* Simulate a real SHA-512 backend leaving the SHA-512 IV in the + * caller's state buffer so the SHA-384 fallback path is forced to + * reset it back to the SHA-384 IV. */ + if (info->hash.sha512 != NULL) { + for (i = 0; i < (int)(sizeof(info->hash.sha512->digest) / + sizeof(info->hash.sha512->digest[0])); i++) { + info->hash.sha512->digest[i] = W64LIT(0xdeadbeefcafebabe); + } + } + return 0; + } + + return CRYPTOCB_UNAVAILABLE; +} +#endif + +int test_wc_CryptoCb_Sha384_Sha512Fallback(void) +{ + EXPECT_DECLS; +#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHA384) && \ + defined(WOLFSSL_SHA512) && !defined(NO_SHA2_CRYPTO_CB) + wc_Sha384 sha; + wc_Sha384 refSha; + Sha384FallbackCbCtx cbCtx; + byte hash[WC_SHA384_DIGEST_SIZE]; + byte devCtxMarker = 0; + int i; + + XMEMSET(&sha, 0, sizeof(sha)); + sha.devId = INVALID_DEVID; + sha.devCtx = NULL; + XMEMSET(&refSha, 0, sizeof(refSha)); + XMEMSET(&cbCtx, 0, sizeof(cbCtx)); + XMEMSET(hash, 0, sizeof(hash)); + + /* Reference struct used to capture the freshly-initialised SHA-384 IV + * state, against which we verify the test struct after Final. */ + ExpectIntEQ(wc_InitSha384_ex(&refSha, HEAP_HINT, INVALID_DEVID), 0); + + ExpectIntEQ(wc_CryptoCb_RegisterDevice( + TEST_CRYPTOCB_SHA384_FALLBACK_DEVID, sha384_fallback_dev_cb, &cbCtx), + 0); + + ExpectIntEQ(wc_InitSha384_ex(&sha, HEAP_HINT, + TEST_CRYPTOCB_SHA384_FALLBACK_DEVID), 0); + sha.devCtx = &devCtxMarker; + + ExpectIntEQ(wc_Sha384Final(&sha, hash), 0); + + ExpectIntEQ(cbCtx.sha384Seen, 1); + ExpectIntEQ(cbCtx.sha512Seen, 1); + + /* devId and devCtx must be preserved across the SHA-512 fallback. */ + ExpectIntEQ(sha.devId, TEST_CRYPTOCB_SHA384_FALLBACK_DEVID); + ExpectPtrEq(sha.devCtx, &devCtxMarker); + + for (i = 0; i < WC_SHA384_DIGEST_SIZE; i++) + ExpectIntEQ(hash[i], (byte)(0x80 + i)); + + /* The SHA-512 fallback leaves the SHA-512 IV in the state buffer; the + * fallback must reset it back to the SHA-384 IV so the struct is ready + * to hash a new message. */ + ExpectIntEQ(XMEMCMP(sha.digest, refSha.digest, sizeof(sha.digest)), 0); + + wc_Sha384Free(&sha); + wc_Sha384Free(&refSha); + wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_SHA384_FALLBACK_DEVID); +#endif + return EXPECT_RESULT(); +} + diff --git a/tests/api/test_sha512.h b/tests/api/test_sha512.h index 48882c4daa..24d015a137 100644 --- a/tests/api/test_sha512.h +++ b/tests/api/test_sha512.h @@ -66,6 +66,7 @@ int test_wc_Sha384_other(void); int test_wc_Sha384Copy(void); int test_wc_Sha384GetHash(void); int test_wc_Sha384_Flags(void); +int test_wc_CryptoCb_Sha384_Sha512Fallback(void); #define TEST_SHA512_DECLS \ TEST_DECL_GROUP("sha512", test_wc_InitSha512), \ @@ -103,15 +104,16 @@ int test_wc_Sha384_Flags(void); TEST_DECL_GROUP("sha512_256", test_wc_Sha512_256Transform), \ TEST_DECL_GROUP("sha512_256", test_wc_Sha512_256_Flags) -#define TEST_SHA384_DECLS \ - TEST_DECL_GROUP("sha384", test_wc_InitSha384), \ - TEST_DECL_GROUP("sha384", test_wc_Sha384Update), \ - TEST_DECL_GROUP("sha384", test_wc_Sha384Final), \ - TEST_DECL_GROUP("sha384", test_wc_Sha384FinalRaw), \ - TEST_DECL_GROUP("sha384", test_wc_Sha384_KATs), \ - TEST_DECL_GROUP("sha384", test_wc_Sha384_other), \ - TEST_DECL_GROUP("sha384", test_wc_Sha384Copy), \ - TEST_DECL_GROUP("sha384", test_wc_Sha384GetHash), \ - TEST_DECL_GROUP("sha384", test_wc_Sha384_Flags) +#define TEST_SHA384_DECLS \ + TEST_DECL_GROUP("sha384", test_wc_InitSha384), \ + TEST_DECL_GROUP("sha384", test_wc_Sha384Update), \ + TEST_DECL_GROUP("sha384", test_wc_Sha384Final), \ + TEST_DECL_GROUP("sha384", test_wc_Sha384FinalRaw), \ + TEST_DECL_GROUP("sha384", test_wc_Sha384_KATs), \ + TEST_DECL_GROUP("sha384", test_wc_Sha384_other), \ + TEST_DECL_GROUP("sha384", test_wc_Sha384Copy), \ + TEST_DECL_GROUP("sha384", test_wc_Sha384GetHash), \ + TEST_DECL_GROUP("sha384", test_wc_Sha384_Flags), \ + TEST_DECL_GROUP("sha384", test_wc_CryptoCb_Sha384_Sha512Fallback) #endif /* WOLFCRYPT_TEST_SHA512_H */ diff --git a/tests/swdev/swdev.c b/tests/swdev/swdev.c index db06f20409..24271eda1e 100644 --- a/tests/swdev/swdev.c +++ b/tests/swdev/swdev.c @@ -249,6 +249,177 @@ static int swdev_sha224(wc_CryptoInfo* info) #endif /* WOLFSSL_SHA224 */ #endif /* !NO_SHA256 */ +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) +/* Copy hash state between caller's wc_Sha512 and swdev's shadow, leaving + * admin fields (heap, devId, devCtx, W, async, HW ctx) per-side. The same + * helper works for SHA-384, SHA-512/224, SHA-512/256 since they all typedef + * to wc_Sha512. */ +static void swdev_sha512_copy_state(wc_Sha512* dst, const wc_Sha512* src) +{ + XMEMCPY(dst->digest, src->digest, sizeof(dst->digest)); + XMEMCPY(dst->buffer, src->buffer, sizeof(dst->buffer)); + dst->buffLen = src->buffLen; + dst->loLen = src->loLen; + dst->hiLen = src->hiLen; +#ifdef WC_C_DYNAMIC_FALLBACK + dst->sha_method = src->sha_method; +#endif +#ifdef WOLFSSL_HASH_FLAGS + dst->flags = src->flags; +#endif +#if defined(WOLFSSL_SHA512_HASHTYPE) + dst->hashType = src->hashType; +#endif +} +#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ + +#ifdef WOLFSSL_SHA512 +static int swdev_sha512(wc_CryptoInfo* info) +{ + wc_Sha512* sha512 = info->hash.sha512; + wc_Sha512 shadow; + int ret; + + if (sha512 == NULL) + return BAD_FUNC_ARG; + + ret = wc_InitSha512(&shadow); + if (ret != 0) + return ret; + + swdev_sha512_copy_state(&shadow, sha512); + + if (info->hash.in != NULL) { + ret = wc_Sha512Update(&shadow, info->hash.in, info->hash.inSz); + if (ret != 0) + goto out; + } + + if (info->hash.digest != NULL) { + ret = wc_Sha512Final(&shadow, info->hash.digest); + if (ret != 0) + goto out; + } + + swdev_sha512_copy_state(sha512, &shadow); + +out: + wc_Sha512Free(&shadow); + return ret; +} + +#if !defined(WOLFSSL_NOSHA512_224) && \ + !defined(WOLFSSL_SWDEV_SHA512_GENERAL_ONLY) +static int swdev_sha512_224(wc_CryptoInfo* info) +{ + wc_Sha512 shadow; + wc_Sha512* sha = info->hash.sha512; + int ret; + + if (sha == NULL) + return BAD_FUNC_ARG; + + ret = wc_InitSha512_224(&shadow); + if (ret != 0) + return ret; + + swdev_sha512_copy_state(&shadow, sha); + + if (info->hash.in != NULL) { + ret = wc_Sha512_224Update(&shadow, info->hash.in, info->hash.inSz); + if (ret != 0) + goto out; + } + if (info->hash.digest != NULL) { + ret = wc_Sha512_224Final(&shadow, info->hash.digest); + if (ret != 0) + goto out; + } + + swdev_sha512_copy_state(sha, &shadow); + +out: + wc_Sha512_224Free(&shadow); + return ret; +} +#endif + +#if !defined(WOLFSSL_NOSHA512_256) && \ + !defined(WOLFSSL_SWDEV_SHA512_GENERAL_ONLY) +static int swdev_sha512_256(wc_CryptoInfo* info) +{ + wc_Sha512 shadow; + wc_Sha512* sha = info->hash.sha512; + int ret; + + if (sha == NULL) + return BAD_FUNC_ARG; + + ret = wc_InitSha512_256(&shadow); + if (ret != 0) + return ret; + + swdev_sha512_copy_state(&shadow, sha); + + if (info->hash.in != NULL) { + ret = wc_Sha512_256Update(&shadow, info->hash.in, info->hash.inSz); + if (ret != 0) + goto out; + } + if (info->hash.digest != NULL) { + ret = wc_Sha512_256Final(&shadow, info->hash.digest); + if (ret != 0) + goto out; + } + + swdev_sha512_copy_state(sha, &shadow); + +out: + wc_Sha512_256Free(&shadow); + return ret; +} +#endif +#endif /* WOLFSSL_SHA512 */ + +#if defined(WOLFSSL_SHA384) && !defined(WOLFSSL_SWDEV_SHA512_GENERAL_ONLY) +/* SHA-384 is SHA-512 with a different IV/truncation; wc_Sha384 is a typedef + * of wc_Sha512, so the shadow/copy-state dance is identical to swdev_sha512. + * When WOLFSSL_SWDEV_SHA512_GENERAL_ONLY is set this is omitted so swdev declines + * SHA-384 and the cryptocb dispatcher's SHA-512 fallback path is exercised. */ +static int swdev_sha384(wc_CryptoInfo* info) +{ + wc_Sha384* sha384 = info->hash.sha384; + wc_Sha384 shadow; + int ret; + + if (sha384 == NULL) + return BAD_FUNC_ARG; + + ret = wc_InitSha384(&shadow); + if (ret != 0) + return ret; + + swdev_sha512_copy_state(&shadow, sha384); + + if (info->hash.in != NULL) { + ret = wc_Sha384Update(&shadow, info->hash.in, info->hash.inSz); + if (ret != 0) + goto out; + } + if (info->hash.digest != NULL) { + ret = wc_Sha384Final(&shadow, info->hash.digest); + if (ret != 0) + goto out; + } + + swdev_sha512_copy_state(sha384, &shadow); + +out: + wc_Sha384Free(&shadow); + return ret; +} +#endif /* WOLFSSL_SHA384 && !WOLFSSL_SWDEV_SHA512_GENERAL_ONLY */ + #ifndef NO_AES /* Rebuild a software AES shadow from the caller's raw devKey, since the * caller's Aes has no software round-key schedule under CB_ONLY_AES. */ @@ -546,14 +717,35 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info, return CRYPTOCB_UNAVAILABLE; } #endif -#ifndef NO_SHA256 +#if !defined(NO_SHA256) || defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) case WC_ALGO_TYPE_HASH: switch (info->hash.type) { + #ifndef NO_SHA256 case WC_HASH_TYPE_SHA256: return swdev_sha256(info); + #endif #ifdef WOLFSSL_SHA224 case WC_HASH_TYPE_SHA224: return swdev_sha224(info); + #endif + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + return swdev_sha512(info); + #if !defined(WOLFSSL_NOSHA512_224) && \ + !defined(WOLFSSL_SWDEV_SHA512_GENERAL_ONLY) + case WC_HASH_TYPE_SHA512_224: + return swdev_sha512_224(info); + #endif + #if !defined(WOLFSSL_NOSHA512_256) && \ + !defined(WOLFSSL_SWDEV_SHA512_GENERAL_ONLY) + case WC_HASH_TYPE_SHA512_256: + return swdev_sha512_256(info); + #endif + #endif + #if defined(WOLFSSL_SHA384) && \ + !defined(WOLFSSL_SWDEV_SHA512_GENERAL_ONLY) + case WC_HASH_TYPE_SHA384: + return swdev_sha384(info); #endif default: return CRYPTOCB_UNAVAILABLE; diff --git a/tests/swdev/user_settings.h b/tests/swdev/user_settings.h index 09073ea2b9..c04f056b02 100644 --- a/tests/swdev/user_settings.h +++ b/tests/swdev/user_settings.h @@ -25,6 +25,7 @@ #undef WOLF_CRYPTO_CB_ONLY_RSA #undef WOLF_CRYPTO_CB_ONLY_ECC #undef WOLF_CRYPTO_CB_ONLY_SHA256 +#undef WOLF_CRYPTO_CB_ONLY_SHA512 #undef WOLF_CRYPTO_CB_ONLY_AES #ifndef WOLF_CRYPTO_CB diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index d647fda7bf..bce3c4aed2 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -2015,16 +2015,48 @@ int wc_CryptoCb_Sha384Hash(wc_Sha384* sha384, const byte* in, } if (dev && dev->cb) { + byte localHash[WC_SHA512_DIGEST_SIZE]; wc_CryptoInfo cryptoInfo; XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); cryptoInfo.algo_type = WC_ALGO_TYPE_HASH; - cryptoInfo.hash.type = WC_HASH_TYPE_SHA384; - cryptoInfo.hash.sha384 = sha384; cryptoInfo.hash.in = in; cryptoInfo.hash.inSz = inSz; + + /* try the SHA-384 callback first */ + cryptoInfo.hash.type = WC_HASH_TYPE_SHA384; + cryptoInfo.hash.sha384 = sha384; cryptoInfo.hash.digest = digest; + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + ret = wc_CryptoCb_TranslateErrorCode(ret); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall back to the SHA-512 core: SHA-384 is the SHA-512 core with a + * different IV (in the caller-supplied state) and a 48-byte + * truncation done here */ + cryptoInfo.hash.type = WC_HASH_TYPE_SHA512; + cryptoInfo.hash.sha512 = (wc_Sha512*)sha384; + /* use local buffer for the final digest so we can truncate */ + if (digest != NULL) + cryptoInfo.hash.digest = localHash; ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + ret = wc_CryptoCb_TranslateErrorCode(ret); + if (ret == 0 && digest != NULL) { + XMEMCPY(digest, localHash, WC_SHA384_DIGEST_SIZE); + /* the SHA-512 callback left the SHA-512 IV in the state; write + * the SHA-384 IV back so the struct is ready for reuse */ + if (sha384 != NULL) { + sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8); + sha384->digest[1] = W64LIT(0x629a292a367cd507); + sha384->digest[2] = W64LIT(0x9159015a3070dd17); + sha384->digest[3] = W64LIT(0x152fecd8f70e5939); + sha384->digest[4] = W64LIT(0x67332667ffc00b31); + sha384->digest[5] = W64LIT(0x8eb44a8768581511); + sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7); + sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4); + } + } + return ret; } return wc_CryptoCb_TranslateErrorCode(ret); diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index 425ad745c2..965a718f66 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -57,7 +57,8 @@ #include #if (defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)) && \ - !defined(WOLFSSL_RISCV_ASM) + !defined(WOLFSSL_RISCV_ASM) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA512) /* determine if we are using Espressif SHA hardware acceleration */ #undef WOLFSSL_USE_ESP32_CRYPT_HASH_HW @@ -2858,3 +2859,504 @@ int wc_Sha384_Grow(wc_Sha384* sha384, const byte* in, int inSz) #endif /* WOLFSSL_SHA384 */ #endif /* WOLFSSL_HASH_KEEP */ #endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ + +/* + * Crypto-callback-only SHA-512 family backend. + * + * Active only when WOLF_CRYPTO_CB_ONLY_SHA512 is defined. Provides the public + * SHA-512, SHA-384, SHA-512/224 and SHA-512/256 API as thin dispatchers over + * the wc_CryptoCb_Sha{384,512}Hash entry points; If the registered callback + * returns CRYPTOCB_UNAVAILABLE every operation surfaces NO_VALID_DEVID. + */ + +#include + +#if defined(WOLF_CRYPTO_CB_ONLY_SHA512) && \ + (defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)) + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* WOLF_CRYPTO_CB_ONLY_SHA512 strips the software SHA-512 implementation and + * routes every operation (SHA-512, SHA-384, SHA-512/224, SHA-512/256) through + * the crypto callback. It is mutually exclusive with any in-tree SHA-512 + * hardware/asm backend: keep this list in sync with the backend dispatch + * chains in sha512.c. */ +#if (defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \ + !defined(WOLFSSL_QNX_CAAM)) || \ + defined(WOLFSSL_SILABS_SHA512) || \ + defined(WOLFSSL_KCAPI_HASH) || \ + (defined(WOLFSSL_RENESAS_RSIP) && \ + !defined(NO_WOLFSSL_RENESAS_FSPSM_HASH)) || \ + defined(MAX3266X_SHA) || \ + (defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)) || \ + defined(STM32_HASH_SHA512) || \ + defined(PSOC6_HASH_SHA2) || \ + defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) || \ + defined(WOLFSSL_ARMASM) || \ + (defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))) + #error "WOLF_CRYPTO_CB_ONLY_SHA512 is incompatible with SHA-512 hardware" \ + " acceleration backends" +#endif +#if defined(HAVE_FIPS) + #error "WOLF_CRYPTO_CB_ONLY_SHA512 is incompatible with FIPS builds" +#endif +/* WOLFSSL_HASH_KEEP accumulates all Update data into sha->msg and passes it + * all to hardware in Final. That pattern is driven by port-specific backends + * (e.g. CAAM) which are already excluded above; the crypto-callback Update + * path dispatches each chunk directly to the callback instead, so the two + * mechanisms are incompatible. */ +#ifdef WOLFSSL_HASH_KEEP + #error "WOLF_CRYPTO_CB_ONLY_SHA512 is incompatible with WOLFSSL_HASH_KEEP" +#endif + +static int Sha512_CbReset(wc_Sha512* sha512, const word64* initDigest, + int hashType) +{ + int i; + + if (sha512 == NULL) + return BAD_FUNC_ARG; + + for (i = 0; i < 8; i++) + sha512->digest[i] = initDigest[i]; + + sha512->buffLen = 0; + XMEMSET(sha512->buffer, 0, sizeof(sha512->buffer)); + sha512->loLen = 0; + sha512->hiLen = 0; +#ifdef WOLFSSL_HASH_FLAGS + sha512->flags = 0; +#endif +#if defined(WOLFSSL_SHA512_HASHTYPE) + sha512->hashType = hashType; +#else + (void)hashType; +#endif + return 0; +} + +static int Sha512_CbInit(wc_Sha512* sha512, const word64* initDigest, + void* heap, int devId, int hashType) +{ + int ret = Sha512_CbReset(sha512, initDigest, hashType); + + if (ret != 0) + return ret; + + sha512->heap = heap; + sha512->devId = devId; + sha512->devCtx = NULL; + + return 0; +} + +#ifdef WOLFSSL_SHA512 + +static const word64 sha512Init[8] = { + W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b), + W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1), + W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f), + W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179) +}; + +static int Sha512_CbFinal(wc_Sha512* sha512, byte* hash, size_t digestSz) +{ + if (sha512 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + #ifndef WOLF_CRYPTO_CB_FIND + if (sha512->devId != INVALID_DEVID) + #endif + { + int ret = wc_CryptoCb_Sha512Hash(sha512, NULL, 0, hash, digestSz); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + } + return NO_VALID_DEVID; +} + +int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId) +{ + return Sha512_CbInit(sha512, sha512Init, heap, devId, + WC_HASH_TYPE_SHA512); +} + +int wc_InitSha512(wc_Sha512* sha512) +{ + int devId = INVALID_DEVID; + +#ifdef WOLF_CRYPTO_CB + devId = wc_CryptoCb_DefaultDevID(); +#endif + return wc_InitSha512_ex(sha512, NULL, devId); +} + +int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) +{ + if (sha512 == NULL) + return BAD_FUNC_ARG; + if (data == NULL && len == 0) + return 0; + if (data == NULL) + return BAD_FUNC_ARG; + + #ifndef WOLF_CRYPTO_CB_FIND + if (sha512->devId != INVALID_DEVID) + #endif + { + int ret = wc_CryptoCb_Sha512Hash(sha512, data, len, NULL, 0); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + } + return NO_VALID_DEVID; +} + +int wc_Sha512Final(wc_Sha512* sha512, byte* hash) +{ + return Sha512_CbFinal(sha512, hash, WC_SHA512_DIGEST_SIZE); +} + +void wc_Sha512Free(wc_Sha512* sha512) +{ + if (sha512 == NULL) + return; + ForceZero(sha512, sizeof(*sha512)); +} + +int wc_Sha512GetHash(wc_Sha512* sha512, byte* hash) +{ + int ret; + wc_Sha512 tmp; + if (sha512 == NULL || hash == NULL) + return BAD_FUNC_ARG; + ret = wc_Sha512Copy(sha512, &tmp); + if (ret == 0) { + ret = wc_Sha512Final(&tmp, hash); + wc_Sha512Free(&tmp); + } + return ret; +} + +int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_COPY) + #ifndef WOLF_CRYPTO_CB_FIND + if (src->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_Copy(src->devId, WC_ALGO_TYPE_HASH, + WC_HASH_TYPE_SHA512, (void*)src, (void*)dst); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when the callback is unavailable */ + } + ret = 0; /* discard CRYPTOCB_UNAVAILABLE before the plain struct copy */ +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_COPY */ + + wc_Sha512Free(dst); + XMEMCPY(dst, src, sizeof(wc_Sha512)); + +#ifdef WOLFSSL_HASH_FLAGS + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#ifdef WOLFSSL_HASH_FLAGS +int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags) +{ + if (sha512) + sha512->flags = flags; + return 0; +} +int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags) +{ + if (sha512 && flags) + *flags = sha512->flags; + return 0; +} +#endif /* WOLFSSL_HASH_FLAGS */ + +#if !defined(WOLFSSL_NOSHA512_224) && !defined(HAVE_SELFTEST) + +static const word64 sha512_224Init[8] = { + W64LIT(0x8c3d37c819544da2), W64LIT(0x73e1996689dcd4d6), + W64LIT(0x1dfab7ae32ff9c82), W64LIT(0x679dd514582f9fcf), + W64LIT(0x0f6d2b697bd44da8), W64LIT(0x77e36f7304c48942), + W64LIT(0x3f9d85a86a1d36c8), W64LIT(0x1112e6ad91d692a1) +}; + +int wc_InitSha512_224_ex(wc_Sha512* sha512, void* heap, int devId) +{ + return Sha512_CbInit(sha512, sha512_224Init, heap, devId, + WC_HASH_TYPE_SHA512_224); +} + +int wc_InitSha512_224(wc_Sha512* sha512) +{ + return wc_InitSha512_224_ex(sha512, NULL, INVALID_DEVID); +} + +int wc_Sha512_224Update(wc_Sha512* sha512, const byte* data, word32 len) +{ + return wc_Sha512Update(sha512, data, len); +} + +int wc_Sha512_224Final(wc_Sha512* sha512, byte* hash) +{ + return Sha512_CbFinal(sha512, hash, WC_SHA512_224_DIGEST_SIZE); +} + +void wc_Sha512_224Free(wc_Sha512* sha512) +{ + wc_Sha512Free(sha512); +} + +int wc_Sha512_224Copy(wc_Sha512* src, wc_Sha512* dst) +{ + return wc_Sha512Copy(src, dst); +} + +int wc_Sha512_224GetHash(wc_Sha512* sha512, byte* hash) +{ + int ret; + wc_Sha512 tmp; + if (sha512 == NULL || hash == NULL) + return BAD_FUNC_ARG; + ret = wc_Sha512_224Copy(sha512, &tmp); + if (ret == 0) { + ret = wc_Sha512_224Final(&tmp, hash); + wc_Sha512_224Free(&tmp); + } + return ret; +} + +#ifdef WOLFSSL_HASH_FLAGS +int wc_Sha512_224SetFlags(wc_Sha512* sha512, word32 flags) +{ + return wc_Sha512SetFlags(sha512, flags); +} +int wc_Sha512_224GetFlags(wc_Sha512* sha512, word32* flags) +{ + return wc_Sha512GetFlags(sha512, flags); +} +#endif /* WOLFSSL_HASH_FLAGS */ + +#endif /* !WOLFSSL_NOSHA512_224 && !HAVE_SELFTEST */ + +#if !defined(WOLFSSL_NOSHA512_256) && !defined(HAVE_SELFTEST) + +static const word64 sha512_256Init[8] = { + W64LIT(0x22312194fc2bf72c), W64LIT(0x9f555fa3c84c64c2), + W64LIT(0x2393b86b6f53b151), W64LIT(0x963877195940eabd), + W64LIT(0x96283ee2a88effe3), W64LIT(0xbe5e1e2553863992), + W64LIT(0x2b0199fc2c85b8aa), W64LIT(0x0eb72ddc81c52ca2) +}; + +int wc_InitSha512_256_ex(wc_Sha512* sha512, void* heap, int devId) +{ + return Sha512_CbInit(sha512, sha512_256Init, heap, devId, + WC_HASH_TYPE_SHA512_256); +} + +int wc_InitSha512_256(wc_Sha512* sha512) +{ + return wc_InitSha512_256_ex(sha512, NULL, INVALID_DEVID); +} + +int wc_Sha512_256Update(wc_Sha512* sha512, const byte* data, word32 len) +{ + return wc_Sha512Update(sha512, data, len); +} + +int wc_Sha512_256Final(wc_Sha512* sha512, byte* hash) +{ + return Sha512_CbFinal(sha512, hash, WC_SHA512_256_DIGEST_SIZE); +} + +void wc_Sha512_256Free(wc_Sha512* sha512) +{ + wc_Sha512Free(sha512); +} + +int wc_Sha512_256Copy(wc_Sha512* src, wc_Sha512* dst) +{ + return wc_Sha512Copy(src, dst); +} + +int wc_Sha512_256GetHash(wc_Sha512* sha512, byte* hash) +{ + int ret; + wc_Sha512 tmp; + if (sha512 == NULL || hash == NULL) + return BAD_FUNC_ARG; + ret = wc_Sha512_256Copy(sha512, &tmp); + if (ret == 0) { + ret = wc_Sha512_256Final(&tmp, hash); + wc_Sha512_256Free(&tmp); + } + return ret; +} + +#ifdef WOLFSSL_HASH_FLAGS +int wc_Sha512_256SetFlags(wc_Sha512* sha512, word32 flags) +{ + return wc_Sha512SetFlags(sha512, flags); +} +int wc_Sha512_256GetFlags(wc_Sha512* sha512, word32* flags) +{ + return wc_Sha512GetFlags(sha512, flags); +} +#endif /* WOLFSSL_HASH_FLAGS */ + +#endif /* !WOLFSSL_NOSHA512_256 && !HAVE_SELFTEST */ + +#endif /* WOLFSSL_SHA512 */ + +#ifdef WOLFSSL_SHA384 + +static const word64 sha384Init[8] = { + W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507), + W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939), + W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511), + W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4) +}; + +int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) +{ + return Sha512_CbInit(sha384, sha384Init, heap, devId, + WC_HASH_TYPE_SHA384); +} + +int wc_InitSha384(wc_Sha384* sha384) +{ + int devId = INVALID_DEVID; + +#ifdef WOLF_CRYPTO_CB + devId = wc_CryptoCb_DefaultDevID(); +#endif + return wc_InitSha384_ex(sha384, NULL, devId); +} + +int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len) +{ + if (sha384 == NULL) + return BAD_FUNC_ARG; + if (data == NULL && len == 0) + return 0; + if (data == NULL) + return BAD_FUNC_ARG; + + #ifndef WOLF_CRYPTO_CB_FIND + if (sha384->devId != INVALID_DEVID) + #endif + { + int ret = wc_CryptoCb_Sha384Hash(sha384, data, len, NULL); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + } + return NO_VALID_DEVID; +} + +int wc_Sha384Final(wc_Sha384* sha384, byte* hash) +{ + if (sha384 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + #ifndef WOLF_CRYPTO_CB_FIND + if (sha384->devId != INVALID_DEVID) + #endif + { + int ret = wc_CryptoCb_Sha384Hash(sha384, NULL, 0, hash); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + } + return NO_VALID_DEVID; +} + +void wc_Sha384Free(wc_Sha384* sha384) +{ + if (sha384 == NULL) + return; + ForceZero(sha384, sizeof(*sha384)); +} + +int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash) +{ + int ret; + wc_Sha384 tmp; + if (sha384 == NULL || hash == NULL) + return BAD_FUNC_ARG; + ret = wc_Sha384Copy(sha384, &tmp); + if (ret == 0) { + ret = wc_Sha384Final(&tmp, hash); + wc_Sha384Free(&tmp); + } + return ret; +} + +int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_COPY) + #ifndef WOLF_CRYPTO_CB_FIND + if (src->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_Copy(src->devId, WC_ALGO_TYPE_HASH, + WC_HASH_TYPE_SHA384, (void*)src, (void*)dst); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when the callback is unavailable */ + } + ret = 0; /* discard CRYPTOCB_UNAVAILABLE before the plain struct copy */ +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_COPY */ + + wc_Sha384Free(dst); + XMEMCPY(dst, src, sizeof(wc_Sha384)); + +#ifdef WOLFSSL_HASH_FLAGS + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#ifdef WOLFSSL_HASH_FLAGS +int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags) +{ + if (sha384) + sha384->flags = flags; + return 0; +} +int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags) +{ + if (sha384 && flags) + *flags = sha384->flags; + return 0; +} +#endif /* WOLFSSL_HASH_FLAGS */ + +#endif /* WOLFSSL_SHA384 */ + +#endif /* WOLF_CRYPTO_CB_ONLY_SHA512 && (WOLFSSL_SHA512 || WOLFSSL_SHA384) */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index dbfeff1895..0a0d085bd1 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -72636,6 +72636,15 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) /* set devId to invalid, so software is used */ info->hash.sha384->devId = INVALID_DEVID; #endif + #if defined(WOLF_CRYPTO_CB_ONLY_SHA512) + #ifdef DEBUG_WOLFSSL + printf("CryptoDevCb: exampleVar %d\n", myCtx->exampleVar); + #endif + if (myCtx->exampleVar == 99) { + info->hash.sha384->devId = devIdArg; + return 0; + } + #endif if (info->hash.in != NULL) { ret = wc_Sha384Update( @@ -72665,6 +72674,15 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) /* set devId to invalid, so software is used */ info->hash.sha512->devId = INVALID_DEVID; #endif + #if defined(WOLF_CRYPTO_CB_ONLY_SHA512) + #ifdef DEBUG_WOLFSSL + printf("CryptoDevCb: exampleVar %d\n", myCtx->exampleVar); + #endif + if (myCtx->exampleVar == 99) { + info->hash.sha512->devId = devIdArg; + return 0; + } + #endif if (info->hash.in != NULL) { ret = wc_Sha512Update( diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index c3ced88da7..9f90a359cf 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -5208,6 +5208,12 @@ blinding by defining WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS." #if defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB) #error "WOLF_CRYPTO_CB_ONLY_SHA256 requires WOLF_CRYPTO_CB" #endif +#if defined(WOLF_CRYPTO_CB_ONLY_SHA512) && !defined(WOLF_CRYPTO_CB) + #error "WOLF_CRYPTO_CB_ONLY_SHA512 requires WOLF_CRYPTO_CB" +#endif +#if defined(WOLF_CRYPTO_CB_ONLY_SHA512) && defined(HAVE_FIPS) + #error "WOLF_CRYPTO_CB_ONLY_SHA512 is incompatible with FIPS builds" +#endif #if defined(WOLF_CRYPTO_CB_ONLY_AES) && !defined(WOLF_CRYPTO_CB) #error "WOLF_CRYPTO_CB_ONLY_AES requires WOLF_CRYPTO_CB" #endif diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index 292021c44b..4491700a2f 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/wolfssl/wolfcrypt/sha512.h @@ -80,6 +80,12 @@ #include #endif +/* no raw hash access when software transform is stripped */ +#if defined(WOLF_CRYPTO_CB_ONLY_SHA512) +#undef WOLFSSL_NO_HASH_RAW +#define WOLFSSL_NO_HASH_RAW +#endif + #define SHA512_NOINLINE WC_NO_INLINE #ifdef WOLFSSL_SHA512 @@ -238,7 +244,9 @@ WOLFSSL_LOCAL void Transform_Sha512_Len_base(wc_Sha512* sha512, WOLFSSL_API int wc_InitSha512(wc_Sha512* sha); WOLFSSL_API int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId); WOLFSSL_API int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len); +#if !defined(WOLF_CRYPTO_CB_ONLY_SHA512) WOLFSSL_API int wc_Sha512FinalRaw(wc_Sha512* sha512, byte* hash); +#endif WOLFSSL_API int wc_Sha512Final(wc_Sha512* sha512, byte* hash); WOLFSSL_API void wc_Sha512Free(wc_Sha512* sha); @@ -253,7 +261,8 @@ WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst); WOLFSSL_API int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags); #endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL) +#if (defined(OPENSSL_EXTRA) || defined(HAVE_CURL)) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA512) WOLFSSL_API int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data); #endif @@ -262,7 +271,9 @@ WOLFSSL_API int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data); WOLFSSL_API int wc_InitSha512_224(wc_Sha512* sha); WOLFSSL_API int wc_InitSha512_224_ex(wc_Sha512* sha, void* heap, int devId); WOLFSSL_API int wc_Sha512_224Update(wc_Sha512* sha, const byte* data, word32 len); +#if !defined(WOLF_CRYPTO_CB_ONLY_SHA512) WOLFSSL_API int wc_Sha512_224FinalRaw(wc_Sha512* sha512, byte* hash); +#endif WOLFSSL_API int wc_Sha512_224Final(wc_Sha512* sha512, byte* hash); WOLFSSL_API void wc_Sha512_224Free(wc_Sha512* sha); WOLFSSL_API int wc_Sha512_224GetHash(wc_Sha512* sha512, byte* hash); @@ -272,7 +283,8 @@ WOLFSSL_API int wc_Sha512_224Copy(wc_Sha512* src, wc_Sha512* dst); WOLFSSL_API int wc_Sha512_224GetFlags(wc_Sha512* sha512, word32* flags); #endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL) +#if (defined(OPENSSL_EXTRA) || defined(HAVE_CURL)) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA512) WOLFSSL_API int wc_Sha512_224Transform(wc_Sha512* sha, const unsigned char* data); #endif /* OPENSSL_EXTRA */ @@ -283,7 +295,9 @@ WOLFSSL_API int wc_Sha512_224Transform(wc_Sha512* sha, WOLFSSL_API int wc_InitSha512_256(wc_Sha512* sha); WOLFSSL_API int wc_InitSha512_256_ex(wc_Sha512* sha, void* heap, int devId); WOLFSSL_API int wc_Sha512_256Update(wc_Sha512* sha, const byte* data, word32 len); +#if !defined(WOLF_CRYPTO_CB_ONLY_SHA512) WOLFSSL_API int wc_Sha512_256FinalRaw(wc_Sha512* sha512, byte* hash); +#endif WOLFSSL_API int wc_Sha512_256Final(wc_Sha512* sha512, byte* hash); WOLFSSL_API void wc_Sha512_256Free(wc_Sha512* sha); WOLFSSL_API int wc_Sha512_256GetHash(wc_Sha512* sha512, byte* hash); @@ -293,7 +307,8 @@ WOLFSSL_API int wc_Sha512_256Copy(wc_Sha512* src, wc_Sha512* dst); WOLFSSL_API int wc_Sha512_256GetFlags(wc_Sha512* sha512, word32* flags); #endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL) +#if (defined(OPENSSL_EXTRA) || defined(HAVE_CURL)) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA512) WOLFSSL_API int wc_Sha512_256Transform(wc_Sha512* sha, const unsigned char* data); #endif /* OPENSSL_EXTRA */ @@ -334,7 +349,9 @@ WOLFSSL_API int wc_Sha512_256Transform(wc_Sha512* sha, WOLFSSL_API int wc_InitSha384(wc_Sha384* sha); WOLFSSL_API int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId); WOLFSSL_API int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len); +#if !defined(WOLF_CRYPTO_CB_ONLY_SHA512) WOLFSSL_API int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash); +#endif WOLFSSL_API int wc_Sha384Final(wc_Sha384* sha384, byte* hash); WOLFSSL_API void wc_Sha384Free(wc_Sha384* sha);