Validate response payload sizes in wh_client.c handlers - #473
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the wolfHSM client-side response handlers against malformed or truncated server replies by validating received payload sizes before parsing/copying, and by avoiding stack buffers in receive paths where the comm layer can memcpy unbounded payload sizes.
Changes:
- Update
src/wh_client.cresponse handlers to (1) validateresp_sizeagainst the overlaid response struct before reading fields likerc, and (2) ensure variable-length payload claims (e.g., key exportlen) fit within the received frame. - Move several response receives (CommInit/CommInfo/CustomCb/KeyEvict) to use the comm client’s internal data buffer (
wh_CommClient_GetDataPtr) to prevent stack overflow from oversized frames. - Add a new malformed-response regression test that drives the client against a raw comm server to inject short/oversized frames and verify handlers reject them safely.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/wh_client.c | Adds defensive response-size validation and switches vulnerable handlers to receive into the comm buffer to prevent stale reads and stack overflows. |
| test-refactor/misc/wh_test_client_malformed_resp.c | New test covering short/truncated fixed-size responses, key export length-vs-received checks, and oversized-frame handling for former stack receive sites. |
| test-refactor/wh_test_list.c | Registers the new malformed-response test in the misc test group. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #473
Scan targets checked: wolfhsm-core-bugs, wolfhsm-src
No new issues found in the changed files. ✅
yosuke-wolfssl
force-pushed
the
fix/resSize
branch
from
July 28, 2026 00:28
0237e94 to
80ddbc0
Compare
This was referenced Jul 28, 2026
yosuke-wolfssl
force-pushed
the
fix/resSize
branch
from
July 28, 2026 01:22
80ddbc0 to
3dba187
Compare
bigbrett
approved these changes
Jul 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
wh_Client_RecvResponse()reports the received payload length but never validates it against the message the caller overlays on the comm buffer. The comm client reuses one buffer for request and response, andwh_CommClient_RecvResponse()copies onlypayload_sizebytes — skipping the copy entirely when the caller passes the comm data pointer itself — so a short reply leaves the tail holding the client's own outbound request bytes.A truncated response therefore reads back as a stale
rc == 0with a garbageid/counter. In the key-export paths it is worse:resp->lenis read from request bytes, andmemcpy(out, packOut, resp->len)reads past the received frame, copying comm-buffer contents out to the caller as key material.Fix (
src/wh_client.c)KeyExportResponse,KeyExportPublicResponsesize < sizeof(*resp)→rc→resp->len > (size - sizeof(*resp))size < sizeof(*resp)before readingrcCommCloseResponseresp_size != 0Where
rclives inside the struct being validated, the checks split across a branch chain so the subtraction is guarded by a preceding sibling branch:Rebased onto #496, which added a bounded
data_sizetowh_Client_RecvResponse(). That fixes the separate stack-overflow issue an earlier revision of this PR addressed by receiving intowh_CommClient_GetDataPtr(), so those four handlers are dropped here and keep upstream's stack structs — exceptKeyEvictResponse, which still needssize < sizeof(resp)since its struct is uninitialized. Follow-up to #457, which applied this check towh_client_she.c.KeyExportDmaResponseand the public-DMA path already validated an exact size and are unchanged. Source-only.Tests
The test added by an earlier revision has been removed. It was
test-refactor/misc/wh_test_client_malformed_resp.c(503 lines), which drove the client against a rawwhCommServerso a reply could carry the correct kind and sequence while declaring a malformed size. Per review, a test reachable only through a fake transport or a hand-built packet is testing the harness, not the fix, so it and itswh_test_list.centry are dropped. This also removes the add/add conflict with #463/#474/#475/#476, which each created the same file.No replacement test is added: a conforming server cannot produce the truncated or oversized frames these guards reject, so the normal
wh_Client_*API has no path to them.Verification
test-refactor: default 45 passed / 26 skipped / 0 failed of 71 ·DMA=149/22/0 ·SHE=151/20/0test/suite clean.-std=c90 -Werror -Wall -Wextra -Wpointer-arith.>→>=,>→<); each mutation failed the suite while the test existed.