Validate SHE client response payload size before use - #457
Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens the SHE client response parsing by validating that the received payload is large enough before overlaying/reading response structs, preventing stale-buffer data from being interpreted as valid output on truncated replies.
Changes:
- Added a shared
_CheckRespSz()guard and applied it at all SHE client receive sites to reject undersized responses before reading fixed fields. - For variable-length ECB/CBC crypt responses, additionally verify the declared
resp->szfits within the bytes actually received before copying. - Added a new
resp_sizeregression test that drives the client against a raw comm server and injects malformed/truncated responses.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/wh_client_she.c | Adds response-size gates before accessing fixed/variable-length response fields and bounds copies to received data. |
| test/wh_test_she.c | Adds a new test that validates client-side rejection of truncated/mis-sized SHE responses. |
💡 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 #457
Scan targets checked: wolfhsm-core-bugs, wolfhsm-src
No new issues found in the changed files. ✅
93c01f8 to
862ff9c
Compare
|
@yosuke-wolfssl, please resolve conflicts |
|
wh_client_crypto and wh_server_crypto have similar checking, but they are in this form: Can we preserve that style? Or is there a reason to change? |
862ff9c to
4c8155d
Compare
|
Hi @padelsbach , One SHE-specific note: I kept the _CheckRespSz call before the resp->rc read. Unlike the crypto path, these handlers must read rc first — error replies carry only the fixed struct, so folding everything into a single pre-rc check would let an error response's indeterminate sz mask the real return code. That leaves the dataSz < sizeof(*resp) disjunct as belt-and-suspenders here, which is consistent with how the crypto helpers carry it too. |
|
@yosuke-wolfssl, couple requests: First, can we remove Second, for the SheEncEcb/EncCbc/DecEcb/DecCbc checks, let's do something like this: Also, can you do a follow-up PR to apply this change to other callers of |
4c8155d to
648d1f9
Compare
|
Hi @padelsbach ,
Regarding to other callers, The real gap is src/wh_client.c (~14 sites, no open PR touches it); KeyExport / KeyExportPublic / KeyExportDma are the same variable-length shape as this bug. wh_client_crypto.c is partly covered by #463/#464/#465/#467, with same convention you suggested. |
|
LGTM, let's give @bigbrett a chance to look it over. |
There was a problem hiding this comment.
In general, I think we need to have a generic way of handling these "fuzz"-style argument validation tests that doesn't require a server in the loop at all. Since we trust the server once connected, we haven't been adding these since it is really verbose and not entirely necessary (more of a defense in depth thing) based on the threat model of wolfHSM on real systems. @padelsbach I know we have talked about this too. Whether its in the form of a test-specific transport backend, or an additional callback injection point, I'd like a way to aggregate all the "fuzz-style" argument validation and input sanitization tests in a readable clean way that can be separate from the logical/functional/unit tests and not require a server at all. No action needed for now.
|
@yosuke-wolfssl needs a rebase then I can merge. |
648d1f9 to
8cabc27
Compare
8cabc27 to
869ae09
Compare
Problem
The SHE client response helpers read
resp->rc,resp->sz, and payload byteswithout first checking that the server actually returned enough data. Fourteen
handlers across
src/wh_client_she.cfollow this pattern (f-5466, CWE-1284,Medium).
SHE reads its response in place from the shared comm buffer — every handler
passes
wh_CommClient_GetDataPtr(c->comm), which returnscontext->data. Thataliasing short-circuits the payload-size check added in
wh_CommClient_RecvResponse:So for SHE the length is never validated in any layer. On a short response the
fields past
payload_sizeare leftover bytes from the previous message: astale
rcreading asWH_SHE_ERC_NO_ERRORturns a failed operation into anapparent success, and the ECB/CBC helpers would trust a stale
resp->szwhencopying out.
Fix (
src/wh_client_she.c)Every
wh_Client_RecvResponse()call site (17 across the 14 handlers) nowvalidates the payload before any field is read:
dataSz < sizeof(*resp)fails withWH_ERROR_ABORTED.require
resp->sz > (dataSz - sizeof(*resp))to fail, ordered after theminimum-size guard so the subtraction cannot wrap.
dataSzis initialized to0so an untouched value can't read as valid.Not included, by design: per-handler group/action checks. The finding also
recommends validating
WH_MESSAGE_GROUP_SHEand the expected action, butwh_Client_RecvResponse()already rejects any response whoseresp_kinddiffers from
c->last_req_kind, andkind = WH_MESSAGE_KIND(group, action)—both are covered for every caller. Duplicating that per handler would be
unreachable code.
Closes f-5466.
Verification
make SHE=1under-std=c90 -Werror -Wall -Wextra -Wpointer-arith.rc=0; SHE coverage all SUCCESS — secure boot (incl. boundary),LoadKey + UID checks, RND, ECB/CBC/CMAC, keywrap interop, write protect,
wrapped-key reboot interop, NVM-less flows.
which is not the memory/UB class.
No negative test injecting a truncated SHE response is included — the in-tree
harness has no fault-injecting transport for this path.