diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index e47ae92f8..3aff70fdd 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -5162,7 +5162,8 @@ int wh_Client_Sha384Dma(whClientContext* ctx, wc_Sha384* sha, const uint8_t* in, static int _xferSha512BlockAndUpdateDigest(whClientContext* ctx, wc_Sha512* sha512, - uint32_t isLastBlock) + uint32_t isLastBlock, + int hashType) { uint16_t group = WH_MESSAGE_GROUP_CRYPTO; uint16_t action = WH_MESSAGE_ACTION_NONE; @@ -5199,10 +5200,13 @@ static int _xferSha512BlockAndUpdateDigest(whClientContext* ctx, /* Send the hash state - this will be 0 on the first block on a properly * initialized sha512 struct */ + /* Source hashType from the dispatcher (info->hash.type) rather + * than sha512->hashType, since some wolfSSL ports do not + * populate the struct field. */ memcpy(req->resumeState.hash, sha512->digest, WC_SHA512_DIGEST_SIZE); req->resumeState.hiLen = sha512->hiLen; req->resumeState.loLen = sha512->loLen; - req->resumeState.hashType = sha512->hashType; + req->resumeState.hashType = hashType; uint32_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req); @@ -5232,7 +5236,7 @@ static int _xferSha512BlockAndUpdateDigest(whClientContext* ctx, /* wolfCrypt allows positive error codes on success in some scenarios */ if (ret >= 0) { WH_DEBUG_CLIENT_VERBOSE("Client SHA512 Res recv: ret=%d", ret); - WH_DEBUG_CLIENT_VERBOSE("hashType: %d\n", sha512->hashType); + WH_DEBUG_CLIENT_VERBOSE("hashType: %d\n", hashType); /* Store the received intermediate hash in the sha512 * context and indicate the field is now valid and * should be passed back and forth to the server */ @@ -5248,12 +5252,18 @@ static int _xferSha512BlockAndUpdateDigest(whClientContext* ctx, return ret; } -int wh_Client_Sha512(whClientContext* ctx, wc_Sha512* sha512, const uint8_t* in, - uint32_t inLen, uint8_t* out) +/* Shared implementation for SHA-512 and its truncated variants + * (SHA-512/224, SHA-512/256). The hashType parameter selects the + * output digest size and the variant-appropriate re-init on + * finalize. Sourcing hashType from the caller (the dispatcher) + * rather than sha512->hashType avoids a dependency on the wolfSSL + * port populating that struct field. */ +static int _doSha512(whClientContext* ctx, wc_Sha512* sha512, + const uint8_t* in, uint32_t inLen, uint8_t* out, + int hashType) { int ret = 0; uint8_t* sha512BufferBytes = (uint8_t*)sha512->buffer; - int hashType = WC_HASH_TYPE_SHA512; /* Caller invoked SHA Update: * wc_CryptoCb_Sha512Hash(sha512, data, len, NULL) */ @@ -5268,7 +5278,8 @@ int wh_Client_Sha512(whClientContext* ctx, wc_Sha512* sha512, const uint8_t* in, sha512BufferBytes[sha512->buffLen++] = in[i++]; } if (sha512->buffLen == WC_SHA512_BLOCK_SIZE) { - ret = _xferSha512BlockAndUpdateDigest(ctx, sha512, 0); + ret = _xferSha512BlockAndUpdateDigest(ctx, sha512, 0, + hashType); sha512->buffLen = 0; } } @@ -5276,7 +5287,7 @@ int wh_Client_Sha512(whClientContext* ctx, wc_Sha512* sha512, const uint8_t* in, /* Process as many full blocks from the input data as we can */ while (ret == 0 && (inLen - i) >= WC_SHA512_BLOCK_SIZE) { memcpy(sha512BufferBytes, in + i, WC_SHA512_BLOCK_SIZE); - ret = _xferSha512BlockAndUpdateDigest(ctx, sha512, 0); + ret = _xferSha512BlockAndUpdateDigest(ctx, sha512, 0, hashType); i += WC_SHA512_BLOCK_SIZE; } @@ -5291,17 +5302,33 @@ int wh_Client_Sha512(whClientContext* ctx, wc_Sha512* sha512, const uint8_t* in, /* Caller invoked SHA finalize: * wc_CryptoCb_Sha512Hash(sha512, NULL, 0, * hash) */ if (ret == 0 && out != NULL) { - ret = _xferSha512BlockAndUpdateDigest(ctx, sha512, 1); + word32 digestSz; + + ret = _xferSha512BlockAndUpdateDigest(ctx, sha512, 1, hashType); + + /* Use the hashType from the dispatcher (info->hash.type) to + * select the correct output size. This is more reliable than + * sha512->hashType which depends on the wolfSSL port setting + * it during init. */ + switch (hashType) { + case WC_HASH_TYPE_SHA512_224: + digestSz = WC_SHA512_224_DIGEST_SIZE; + break; + case WC_HASH_TYPE_SHA512_256: + digestSz = WC_SHA512_256_DIGEST_SIZE; + break; + default: + digestSz = WC_SHA512_DIGEST_SIZE; + break; + } /* Copy out the final hash value */ if (ret == 0) { - memcpy(out, sha512->digest, WC_SHA512_DIGEST_SIZE); + memcpy(out, sha512->digest, digestSz); } - /* keep hashtype before initialization */ - hashType = sha512->hashType; - /* reset the state of the sha context (without blowing away devId and - * hashType) - */ + + /* Reset the sha context for potential reuse, calling the + * variant-appropriate init to preserve devId and hashType */ switch (hashType) { case WC_HASH_TYPE_SHA512_224: (void)wc_InitSha512_224_ex(sha512, NULL, sha512->devId); @@ -5318,9 +5345,32 @@ int wh_Client_Sha512(whClientContext* ctx, wc_Sha512* sha512, const uint8_t* in, return ret; } +int wh_Client_Sha512(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, + uint32_t inLen, uint8_t* out) +{ + return _doSha512(ctx, sha, in, inLen, out, WC_HASH_TYPE_SHA512); +} + +#if !defined(WOLFSSL_NOSHA512_224) +int wh_Client_Sha512_224(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, uint8_t* out) +{ + return _doSha512(ctx, sha, in, inLen, out, WC_HASH_TYPE_SHA512_224); +} +#endif /* !WOLFSSL_NOSHA512_224 */ + +#if !defined(WOLFSSL_NOSHA512_256) +int wh_Client_Sha512_256(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, uint8_t* out) +{ + return _doSha512(ctx, sha, in, inLen, out, WC_HASH_TYPE_SHA512_256); +} +#endif /* !WOLFSSL_NOSHA512_256 */ + #ifdef WOLFHSM_CFG_DMA -int wh_Client_Sha512Dma(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, - uint32_t inLen, uint8_t* out) +static int _doSha512Dma(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, uint8_t* out, + int hashType) { int ret = WH_ERROR_OK; wc_Sha512* sha512 = sha; @@ -5332,6 +5382,20 @@ int wh_Client_Sha512Dma(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, uintptr_t inAddr = 0; uintptr_t outAddr = 0; uintptr_t stateAddr = 0; + word32 digestSz; + + /* Select digest size based on variant */ + switch (hashType) { + case WC_HASH_TYPE_SHA512_224: + digestSz = WC_SHA512_224_DIGEST_SIZE; + break; + case WC_HASH_TYPE_SHA512_256: + digestSz = WC_SHA512_256_DIGEST_SIZE; + break; + default: + digestSz = WC_SHA512_DIGEST_SIZE; + break; + } /* Get data pointer from the context to use as request/response storage */ dataPtr = (uint8_t*)wh_CommClient_GetDataPtr(ctx->comm); @@ -5339,14 +5403,18 @@ int wh_Client_Sha512Dma(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, return WH_ERROR_BADARGS; } - /* Setup generic header and get pointer to request data */ + /* Setup generic header and get pointer to request data. The + * algorithm-category is always WC_HASH_TYPE_SHA512 at this layer; + * the server's top-level dispatcher keys on this to find the + * SHA512 handler. The specific variant (512/224/256) is handled + * internally via sha512->hashType on the server side. */ req = (whMessageCrypto_Sha2DmaRequest*)_createCryptoRequest( dataPtr, WC_HASH_TYPE_SHA512, ctx->cryptoAffinity); if (in != NULL || out != NULL) { req->state.sz = sizeof(*sha512); req->input.sz = inLen; - req->output.sz = WC_SHA512_DIGEST_SIZE; /* not needed, but YOLO */ + req->output.sz = digestSz; /* Perform address translations */ ret = wh_Client_DmaProcessClientAddress( @@ -5398,8 +5466,8 @@ int wh_Client_Sha512Dma(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, * rc */ ret = _getCryptoResponse(dataPtr, WC_HASH_TYPE_SHA512, (uint8_t**)&resp); - /* Nothing to do on success, as server will have updated the context - * in client memory */ + /* Nothing to do on success, as server will have updated the + * context in client memory */ } } @@ -5429,8 +5497,8 @@ int wh_Client_Sha512Dma(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, * rc */ ret = _getCryptoResponse(dataPtr, WC_HASH_TYPE_SHA512, (uint8_t**)&resp); - /* Nothing to do on success, as server will have updated the output - * hash in client memory */ + /* Nothing to do on success, as server will have updated the + * output hash in client memory */ } } @@ -5442,12 +5510,38 @@ int wh_Client_Sha512Dma(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, ctx, (uintptr_t)in, (void**)&inAddr, inLen, WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); (void)wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)out, (void**)&outAddr, WC_SHA512_DIGEST_SIZE, + ctx, (uintptr_t)out, (void**)&outAddr, digestSz, WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0}); } return ret; } -#endif /* WOLFHSM_CFG_DMA */ + +int wh_Client_Sha512Dma(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, uint8_t* out) +{ + return _doSha512Dma(ctx, sha, in, inLen, out, WC_HASH_TYPE_SHA512); +} + +#if !defined(WOLFSSL_NOSHA512_224) +int wh_Client_Sha512_224Dma(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, + uint8_t* out) +{ + return _doSha512Dma(ctx, sha, in, inLen, out, + WC_HASH_TYPE_SHA512_224); +} +#endif /* !WOLFSSL_NOSHA512_224 */ + +#if !defined(WOLFSSL_NOSHA512_256) +int wh_Client_Sha512_256Dma(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, + uint8_t* out) +{ + return _doSha512Dma(ctx, sha, in, inLen, out, + WC_HASH_TYPE_SHA512_256); +} +#endif /* !WOLFSSL_NOSHA512_256 */ +#endif /* WOLFHSM_CFG_DMA */ #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_DILITHIUM diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index 43ff0a32e..e3c809926 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -522,6 +522,26 @@ int wh_Client_CryptoCb(int devId, wc_CryptoInfo* info, void* inCtx) ret = wh_Client_Sha512(ctx, sha, in, inLen, out); } break; +#if !defined(WOLFSSL_NOSHA512_224) + case WC_HASH_TYPE_SHA512_224: { + wc_Sha512* sha = info->hash.sha512; + const uint8_t* in = info->hash.in; + uint32_t inLen = info->hash.inSz; + uint8_t* out = info->hash.digest; + + ret = wh_Client_Sha512_224(ctx, sha, in, inLen, out); + } break; +#endif /* !WOLFSSL_NOSHA512_224 */ +#if !defined(WOLFSSL_NOSHA512_256) + case WC_HASH_TYPE_SHA512_256: { + wc_Sha512* sha = info->hash.sha512; + const uint8_t* in = info->hash.in; + uint32_t inLen = info->hash.inSz; + uint8_t* out = info->hash.digest; + + ret = wh_Client_Sha512_256(ctx, sha, in, inLen, out); + } break; +#endif /* !WOLFSSL_NOSHA512_256 */ #endif /* WOLFSSL_SHA512 && WOLFSSL_SHA512_HASHTYPE */ default: ret = CRYPTOCB_UNAVAILABLE; @@ -847,7 +867,27 @@ int wh_Client_CryptoCbDma(int devId, wc_CryptoInfo* info, void* inCtx) ret = wh_Client_Sha512Dma(ctx, sha, in, inLen, out); } break; -#endif /* WOLFSSL_SHA512 && defined(WOLFSSL_SHA512_HASHTYPE) */ +#if !defined(WOLFSSL_NOSHA512_224) + case WC_HASH_TYPE_SHA512_224: { + wc_Sha512* sha = info->hash.sha512; + const uint8_t* in = info->hash.in; + uint32_t inLen = info->hash.inSz; + uint8_t* out = info->hash.digest; + + ret = wh_Client_Sha512_224Dma(ctx, sha, in, inLen, out); + } break; +#endif /* !WOLFSSL_NOSHA512_224 */ +#if !defined(WOLFSSL_NOSHA512_256) + case WC_HASH_TYPE_SHA512_256: { + wc_Sha512* sha = info->hash.sha512; + const uint8_t* in = info->hash.in; + uint32_t inLen = info->hash.inSz; + uint8_t* out = info->hash.digest; + + ret = wh_Client_Sha512_256Dma(ctx, sha, in, inLen, out); + } break; +#endif /* !WOLFSSL_NOSHA512_256 */ +#endif /* WOLFSSL_SHA512 && WOLFSSL_SHA512_HASHTYPE */ default: ret = CRYPTOCB_UNAVAILABLE; break; diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index 0217912fe..c0535c1bb 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -1950,6 +1950,329 @@ static int whTest_CryptoSha512(whClientContext* ctx, int devId, WC_RNG* rng) } return ret; } + +#if !defined(WOLFSSL_NOSHA512_224) +static int whTest_CryptoSha512_224(whClientContext* ctx, int devId, + WC_RNG* rng) +{ + (void)ctx; + (void)rng; + int ret = WH_ERROR_OK; + wc_Sha512 sha512[1]; + /* Buffer sized for the variant, plus canary to detect overwrite */ + uint8_t out[WC_SHA512_224_DIGEST_SIZE + 8]; + const uint8_t canary = 0xA5; + int i; + /* Same one-block input vector as the SHA512 test */ + const char inOne[] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const uint8_t expectedOutOne[WC_SHA512_224_DIGEST_SIZE] = { + 0x26, 0x1b, 0x94, 0xbc, 0xba, 0x55, 0x42, 0x64, + 0xb3, 0xb7, 0x38, 0xe9, 0xe0, 0x9e, 0x7d, 0xc6, + 0x8a, 0xc8, 0xe0, 0xb4, 0xc8, 0x51, 0x7f, 0xe9, + 0xbb, 0x7c, 0x36, 0x17}; + /* Vector long enough to span a SHA512 block */ + const char inMulti[] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX" + "YZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX" + "YZ1234567890abcdefghi"; + const uint8_t expectedOutMulti[WC_SHA512_224_DIGEST_SIZE] = { + 0xd2, 0x5b, 0x9a, 0xd1, 0x3e, 0xa4, 0xba, 0xc5, + 0x7b, 0xdd, 0x0a, 0x9f, 0xbb, 0x97, 0xb8, 0xc5, + 0x58, 0xdc, 0x13, 0xbc, 0x7a, 0xaa, 0x71, 0xd8, + 0xb6, 0x21, 0xf5, 0xeb}; + + /* Fill canary bytes after the digest area */ + memset(out, canary, sizeof(out)); + + ret = wc_InitSha512_224_ex(sha512, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_InitSha512_224 on devId 0x%X: " + "%d\n", devId, ret); + } + else { + /* Simulate a wolfSSL port that does not populate hashType, + * to verify the wolfHSM client no longer reads it. + * Note: this does not catch a broken hashType propagation + * to the server because SHA512/224 and /256 are truncations + * of SHA512, so software server behavior is unchanged. + * It does verify the client uses the dispatcher-supplied + * hashType for digest sizing and re-init. */ + sha512->hashType = 0; + ret = wc_Sha512_224Update(sha512, (const byte*)inOne, + WC_SHA512_BLOCK_SIZE); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_224Update %d\n", ret); + } + else { + ret = wc_Sha512_224Final(sha512, out); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_224Final %d\n", + ret); + } + else { + if (memcmp(out, expectedOutOne, + WC_SHA512_224_DIGEST_SIZE) != 0) { + WH_ERROR_PRINT("SHA512/224 hash mismatch.\n"); + ret = -1; + } + else { + /* Verify canary was not overwritten */ + for (i = WC_SHA512_224_DIGEST_SIZE; + i < (int)sizeof(out); i++) { + if (out[i] != canary) { + WH_ERROR_PRINT("SHA512/224 overwrote " + "buffer at byte %d\n", i); + ret = -1; + break; + } + } + } + } + } + (void)wc_Sha512_224Free(sha512); + } + + /* Multiblock test. Splits the input across three Updates to + * exercise block-aligned and non-aligned boundaries, which + * drive multiple server transactions. */ + if (ret == 0) { + memset(out, canary, sizeof(out)); + ret = wc_InitSha512_224_ex(sha512, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_InitSha512_224 for devId " + "0x%X: %d\n", devId, ret); + } + else { + sha512->hashType = 0; + /* Update with non-block aligned length (buffered) */ + ret = wc_Sha512_224Update(sha512, (const byte*)inMulti, 1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_224Update " + "(first) %d\n", ret); + } + else { + /* Full block, triggers server transaction plus a + * buffered byte */ + ret = wc_Sha512_224Update(sha512, + (const byte*)inMulti + 1, + WC_SHA512_BLOCK_SIZE); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_224Update " + "(mid) %d\n", ret); + } + else { + ret = wc_Sha512_224Update( + sha512, + (const byte*)inMulti + 1 + WC_SHA512_BLOCK_SIZE, + strlen(inMulti) - 1 - WC_SHA512_BLOCK_SIZE); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_224Update " + "(last) %d\n", ret); + } + else { + ret = wc_Sha512_224Final(sha512, out); + if (ret != 0) { + WH_ERROR_PRINT("Failed to " + "wc_Sha512_224Final %d\n", + ret); + } + else if (memcmp(out, expectedOutMulti, + WC_SHA512_224_DIGEST_SIZE) + != 0) { + WH_ERROR_PRINT("SHA512/224 multi-block " + "hash mismatch.\n"); + ret = -1; + } + else { + /* Canary check */ + for (i = WC_SHA512_224_DIGEST_SIZE; + i < (int)sizeof(out); i++) { + if (out[i] != canary) { + WH_ERROR_PRINT("SHA512/224 " + "overwrote buffer " + "at byte %d\n", i); + ret = -1; + break; + } + } + } + } + } + } + (void)wc_Sha512_224Free(sha512); + } + } + + if (ret == 0) { + WH_TEST_PRINT("SHA512/224 DEVID=0x%X SUCCESS\n", devId); + } + return ret; +} +#endif /* !WOLFSSL_NOSHA512_224 */ + +#if !defined(WOLFSSL_NOSHA512_256) +static int whTest_CryptoSha512_256(whClientContext* ctx, int devId, + WC_RNG* rng) +{ + (void)ctx; + (void)rng; + int ret = WH_ERROR_OK; + wc_Sha512 sha512[1]; + /* Buffer sized for the variant, plus canary to detect overwrite */ + uint8_t out[WC_SHA512_256_DIGEST_SIZE + 8]; + const uint8_t canary = 0xA5; + int i; + /* Same one-block input vector as the SHA512 test */ + const char inOne[] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const uint8_t expectedOutOne[WC_SHA512_256_DIGEST_SIZE] = { + 0xb8, 0x8f, 0x97, 0xe2, 0x74, 0xf9, 0xc1, 0xd4, + 0x9f, 0x18, 0x1c, 0x8c, 0xbd, 0x01, 0xa9, 0xc7, + 0x49, 0x30, 0xad, 0x05, 0x5a, 0x46, 0xac, 0x44, + 0x99, 0xa1, 0xd6, 0x01, 0xf1, 0xc8, 0x0b, 0xf2}; + /* Vector long enough to span a SHA512 block */ + const char inMulti[] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX" + "YZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX" + "YZ1234567890abcdefghi"; + const uint8_t expectedOutMulti[WC_SHA512_256_DIGEST_SIZE] = { + 0xfc, 0x0d, 0x2a, 0xdc, 0xee, 0x1c, 0x15, 0x55, + 0x2f, 0x19, 0x0f, 0x19, 0x5e, 0xe2, 0xe6, 0x33, + 0x8a, 0x56, 0xa6, 0xed, 0x2b, 0x20, 0x22, 0x00, + 0xfd, 0xfc, 0x8f, 0x77, 0x2a, 0x83, 0x81, 0x6e}; + + /* Fill canary bytes after the digest area */ + memset(out, canary, sizeof(out)); + + ret = wc_InitSha512_256_ex(sha512, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_InitSha512_256 on devId 0x%X: " + "%d\n", devId, ret); + } + else { + /* Simulate a wolfSSL port that does not populate hashType, + * to verify the wolfHSM client no longer reads it. + * Note: this does not catch a broken hashType propagation + * to the server because SHA512/224 and /256 are truncations + * of SHA512, so software server behavior is unchanged. + * It does verify the client uses the dispatcher-supplied + * hashType for digest sizing and re-init. */ + sha512->hashType = 0; + ret = wc_Sha512_256Update(sha512, (const byte*)inOne, + WC_SHA512_BLOCK_SIZE); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_256Update %d\n", ret); + } + else { + ret = wc_Sha512_256Final(sha512, out); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_256Final %d\n", + ret); + } + else { + if (memcmp(out, expectedOutOne, + WC_SHA512_256_DIGEST_SIZE) != 0) { + WH_ERROR_PRINT("SHA512/256 hash mismatch.\n"); + ret = -1; + } + else { + /* Verify canary was not overwritten */ + for (i = WC_SHA512_256_DIGEST_SIZE; + i < (int)sizeof(out); i++) { + if (out[i] != canary) { + WH_ERROR_PRINT("SHA512/256 overwrote " + "buffer at byte %d\n", i); + ret = -1; + break; + } + } + } + } + } + (void)wc_Sha512_256Free(sha512); + } + + /* Multiblock test. Splits the input across three Updates to + * exercise block-aligned and non-aligned boundaries, which + * drive multiple server transactions. */ + if (ret == 0) { + memset(out, canary, sizeof(out)); + ret = wc_InitSha512_256_ex(sha512, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_InitSha512_256 for devId " + "0x%X: %d\n", devId, ret); + } + else { + sha512->hashType = 0; + /* Update with non-block aligned length (buffered) */ + ret = wc_Sha512_256Update(sha512, (const byte*)inMulti, 1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_256Update " + "(first) %d\n", ret); + } + else { + /* Full block, triggers server transaction plus a + * buffered byte */ + ret = wc_Sha512_256Update(sha512, + (const byte*)inMulti + 1, + WC_SHA512_BLOCK_SIZE); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_256Update " + "(mid) %d\n", ret); + } + else { + ret = wc_Sha512_256Update( + sha512, + (const byte*)inMulti + 1 + WC_SHA512_BLOCK_SIZE, + strlen(inMulti) - 1 - WC_SHA512_BLOCK_SIZE); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_Sha512_256Update " + "(last) %d\n", ret); + } + else { + ret = wc_Sha512_256Final(sha512, out); + if (ret != 0) { + WH_ERROR_PRINT("Failed to " + "wc_Sha512_256Final %d\n", + ret); + } + else if (memcmp(out, expectedOutMulti, + WC_SHA512_256_DIGEST_SIZE) + != 0) { + WH_ERROR_PRINT("SHA512/256 multi-block " + "hash mismatch.\n"); + ret = -1; + } + else { + /* Canary check */ + for (i = WC_SHA512_256_DIGEST_SIZE; + i < (int)sizeof(out); i++) { + if (out[i] != canary) { + WH_ERROR_PRINT("SHA512/256 " + "overwrote buffer " + "at byte %d\n", i); + ret = -1; + break; + } + } + } + } + } + } + (void)wc_Sha512_256Free(sha512); + } + } + + if (ret == 0) { + WH_TEST_PRINT("SHA512/256 DEVID=0x%X SUCCESS\n", devId); + } + return ret; +} +#endif /* !WOLFSSL_NOSHA512_256 */ + #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_HKDF @@ -5915,6 +6238,24 @@ int whTest_CryptoClientConfig(whClientConfig* config) i++; } } +#if !defined(WOLFSSL_NOSHA512_224) + i = 0; + while ((ret == WH_ERROR_OK) && (i < WH_NUM_DEVIDS)) { + ret = whTest_CryptoSha512_224(client, WH_DEV_IDS_ARRAY[i], rng); + if (ret == WH_ERROR_OK) { + i++; + } + } +#endif /* !WOLFSSL_NOSHA512_224 */ +#if !defined(WOLFSSL_NOSHA512_256) + i = 0; + while ((ret == WH_ERROR_OK) && (i < WH_NUM_DEVIDS)) { + ret = whTest_CryptoSha512_256(client, WH_DEV_IDS_ARRAY[i], rng); + if (ret == WH_ERROR_OK) { + i++; + } + } +#endif /* !WOLFSSL_NOSHA512_256 */ #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_HKDF diff --git a/wolfhsm/wh_client_crypto.h b/wolfhsm/wh_client_crypto.h index b09514a28..73d3e186c 100644 --- a/wolfhsm/wh_client_crypto.h +++ b/wolfhsm/wh_client_crypto.h @@ -998,8 +998,8 @@ int wh_Client_Sha384Dma(whClientContext* ctx, wc_Sha384* sha, const uint8_t* in, /** * @brief Performs a SHA-512 hash operation on the input data. * - * This function performs a SHA-512 hash operation on the input data and stores - * the result in the output buffer. + * This function performs a SHA-512 hash operation on the input data + * and stores the result in the output buffer. * * @param[in] ctx Pointer to the client context structure. * @param[in] sha Pointer to the SHA-512 context structure. @@ -1010,11 +1010,42 @@ int wh_Client_Sha384Dma(whClientContext* ctx, wc_Sha384* sha, const uint8_t* in, */ int wh_Client_Sha512(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, uint32_t inLen, uint8_t* out); + +#if !defined(WOLFSSL_NOSHA512_224) +/** + * @brief Performs a SHA-512/224 hash operation on the input data. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] sha Pointer to the SHA-512 context structure. + * @param[in] in Pointer to the input data. + * @param[in] inLen Length of the input data in bytes. + * @param[out] out Pointer to the output buffer (28 bytes). + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_Sha512_224(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, uint8_t* out); +#endif /* !WOLFSSL_NOSHA512_224 */ + +#if !defined(WOLFSSL_NOSHA512_256) +/** + * @brief Performs a SHA-512/256 hash operation on the input data. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] sha Pointer to the SHA-512 context structure. + * @param[in] in Pointer to the input data. + * @param[in] inLen Length of the input data in bytes. + * @param[out] out Pointer to the output buffer (32 bytes). + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_Sha512_256(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, uint8_t* out); +#endif /* !WOLFSSL_NOSHA512_256 */ + /** * @brief Performs a SHA-512 hash operation on the input data using DMA. * - * This function performs a SHA-512 hash operation on the input data and stores - * the result in the output buffer using DMA. + * This function performs a SHA-512 hash operation on the input data + * and stores the result in the output buffer using DMA. * * @param[in] ctx Pointer to the client context structure. * @param[in] sha Pointer to the SHA-512 context structure. @@ -1025,6 +1056,38 @@ int wh_Client_Sha512(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, */ int wh_Client_Sha512Dma(whClientContext* ctx, wc_Sha512* sha, const uint8_t* in, uint32_t inLen, uint8_t* out); + +#if !defined(WOLFSSL_NOSHA512_224) +/** + * @brief Performs a SHA-512/224 hash operation using DMA. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] sha Pointer to the SHA-512 context structure. + * @param[in] in Pointer to the input data. + * @param[in] inLen Length of the input data in bytes. + * @param[out] out Pointer to the output buffer (28 bytes). + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_Sha512_224Dma(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, + uint8_t* out); +#endif /* !WOLFSSL_NOSHA512_224 */ + +#if !defined(WOLFSSL_NOSHA512_256) +/** + * @brief Performs a SHA-512/256 hash operation using DMA. + * + * @param[in] ctx Pointer to the client context structure. + * @param[in] sha Pointer to the SHA-512 context structure. + * @param[in] in Pointer to the input data. + * @param[in] inLen Length of the input data in bytes. + * @param[out] out Pointer to the output buffer (32 bytes). + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_Sha512_256Dma(whClientContext* ctx, wc_Sha512* sha, + const uint8_t* in, uint32_t inLen, + uint8_t* out); +#endif /* !WOLFSSL_NOSHA512_256 */ #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_DILITHIUM