Skip to content

Validate response payload sizes in wh_client.c handlers - #473

Merged
bigbrett merged 1 commit into
wolfSSL:mainfrom
yosuke-wolfssl:fix/resSize
Jul 28, 2026
Merged

Validate response payload sizes in wh_client.c handlers#473
bigbrett merged 1 commit into
wolfSSL:mainfrom
yosuke-wolfssl:fix/resSize

Conversation

@yosuke-wolfssl

@yosuke-wolfssl yosuke-wolfssl commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

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, and wh_CommClient_RecvResponse() copies only payload_size bytes — 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 == 0 with a garbage id/counter. In the key-export paths it is worse: resp->len is read from request bytes, and memcpy(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)

Handlers Change
KeyExportResponse, KeyExportPublicResponse size < sizeof(*resp)rcresp->len > (size - sizeof(*resp))
6 keystore + 4 counter fixed-size responses size < sizeof(*resp) before reading rc
CommCloseResponse resp_size != 0

Where rc lives inside the struct being validated, the checks split across a branch chain so the subtraction is guarded by a preceding sibling branch:

if (size < sizeof(*resp))                        { ret = WH_ERROR_ABORTED; }
else if (resp->rc != 0)                          { ret = resp->rc; }
else if (resp->len > (size - sizeof(*resp)))     { ret = WH_ERROR_ABORTED; }

Rebased onto #496, which added a bounded data_size to wh_Client_RecvResponse(). That fixes the separate stack-overflow issue an earlier revision of this PR addressed by receiving into wh_CommClient_GetDataPtr(), so those four handlers are dropped here and keep upstream's stack structs — except KeyEvictResponse, which still needs size < sizeof(resp) since its struct is uninitialized. Follow-up to #457, which applied this check to wh_client_she.c. KeyExportDmaResponse and 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 raw whCommServer so 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 its wh_test_list.c entry 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=1 49/22/0 · SHE=1 51/20/0
  • Legacy test/ suite clean.
  • Clean under -std=c90 -Werror -Wall -Wextra -Wpointer-arith.
  • Every guard was previously mutation-checked (deleted, >>=, ><); each mutation failed the suite while the test existed.

@yosuke-wolfssl yosuke-wolfssl self-assigned this Jul 22, 2026
Copilot AI review requested due to automatic review settings July 22, 2026 01:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.c response handlers to (1) validate resp_size against the overlaid response struct before reading fields like rc, and (2) ensure variable-length payload claims (e.g., key export len) 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 wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #473

Scan targets checked: wolfhsm-core-bugs, wolfhsm-src

No new issues found in the changed files. ✅

@bigbrett
bigbrett merged commit 84f86a3 into wolfSSL:main Jul 28, 2026
108 checks passed
@yosuke-wolfssl
yosuke-wolfssl deleted the fix/resSize branch July 29, 2026 22:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants