Skip to content

Fix out-of-bounds read in slh_dsa verify on short signature - #2587

Open
Ramya-9353 wants to merge 2 commits into
open-quantum-safe:mainfrom
Ramya-9353:slh-dsa-verify-length-check
Open

Ramya-9353 wants to merge 2 commits into
open-quantum-safe:mainfrom
Ramya-9353:slh-dsa-verify-length-check

Conversation

@Ramya-9353

@Ramya-9353 Ramya-9353 commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

slh_verify and slh_verify_internal call Hmsg before validating the signature length:

  • Hmsg reads the n-byte randomiser R from the front of sig, but the only length check (sig_sz != slh_sig_sz) lives in slh_verify_digest and runs afterwards
  • a signature shorter than n is read out of bounds. ASan on the unpatched tree: heap-buffer-overflow READ of size 16 in sha2_256_h_msg via slh_verify (slh_dsa.c:715), reachable from OQS_SIG_verify with an 8-byte signature buffer for SLH-DSA-SHA2-128f
  • per review, the fix is taken from upstream: the pinned slhdsa-c commit in copy_from_slh_dsa_c.py is bumped to d25ccc6 (Validate signature length to prevent OOB read pq-code-package/slhdsa-c#48), which hoists the sig_sz != slh_sig_sz(prm) check ahead of Hmsg in both entry points; verify_bounds.patch is dropped since the check now arrives with the copied source
  • tests/test_sig.c rejects a 1-byte signature and aborts under ASan without the fix

Valid sign/verify and the existing EUF-CMA test are unchanged. The bump also picks up upstream CBMC contract annotations and a sha3_init cleanup; no algorithm behaviour changes. The root cause was in the vendored slhdsa-c and was fixed upstream in pq-code-package/slhdsa-c#48.

  • Does this PR change the input/output behaviour of a cryptographic algorithm (i.e., does it change known answer test values)? (If so, a version bump will be required from x.y.z to x.(y+1).0.)
  • Does this PR change the list of algorithms available -- either adding, removing, or renaming? Does this PR otherwise change an API?

Generative AI (Claude, via an automated assistant) was used to help locate the issue, write the patch and the regression test, and draft this description. I reviewed and verified the change, the ASan reproducer, and the before/after test behaviour locally.

Signed-off-by: Ramya Eliger <ramya@digiscrypt.com>
@coveralls

coveralls commented Sep 23, 2026 •

Copy link
Copy Markdown

Coverage Status

coverage: 80.297% (-0.06%) from 80.36% — Ramya-9353:slh-dsa-verify-length-check into open-quantum-safe:main

@Ramya-9353

Copy link
Copy Markdown
Contributor Author

any update here?

@xuganyu96

Copy link
Copy Markdown
Contributor

The root cause is in the vendored slhdsa-c; I will report it upstream as well.

Could you please link to the corresponding issue/pull request?

@Ramya-9353

Copy link
Copy Markdown
Contributor Author

It turned out to be fixed upstream already, so there was nothing new for me to file: pq-code-package/slhdsa-c#48, merged 11 June 2026 as d25ccc6. That is the same change this PR carries, the sig_sz != slh_sig_sz(prm) check hoisted ahead of Hmsg in both slh_verify and slh_verify_internal.

liboqs still has the out-of-bounds read because copy_from_slh_dsa_c.py pins a0fc1ff (22 July 2025), which predates that merge. So it can go either way: the carried patch here, or bumping the pinned commit. If you'd rather bump the pin, verify_bounds.patch should be dropped in the same change, since the check would already be in the copied source.

@xuganyu96

Copy link
Copy Markdown
Contributor

It turned out to be fixed upstream already, so there was nothing new for me to file: pq-code-package/slhdsa-c#48, merged 11 June 2026 as d25ccc6. That is the same change this PR carries, the sig_sz != slh_sig_sz(prm) check hoisted ahead of Hmsg in both slh_verify and slh_verify_internal.

liboqs still has the out-of-bounds read because copy_from_slh_dsa_c.py pins a0fc1ff (22 July 2025), which predates that merge. So it can go either way: the carried patch here, or bumping the pinned commit. If you'd rather bump the pin, verify_bounds.patch should be dropped in the same change, since the check would already be in the copied source.

Please bump the pin. Thank you.

Per review, take the upstream fix for the out-of-bounds read
(pq-code-package/slhdsa-c#48, merged as d25ccc6) by bumping the pinned
commit in copy_from_slh_dsa_c.py and dropping verify_bounds.patch.
The regenerated slh_dsa_c tree also picks up upstream CBMC contract
annotations and a sha3_init cleanup; no algorithm behaviour changes.
The short-signature regression test in tests/test_sig.c is kept and
passes under ASan.

Signed-off-by: Ramya Eliger <ramya@digiscrypt.com>
@Ramya-9353

Copy link
Copy Markdown
Contributor Author

Done — bumped the pin to d25ccc6 and dropped verify_bounds.patch; the length check now comes in with the copied upstream source. The bump also brings in upstream's CBMC contract annotations and a sha3_init cleanup, no behaviour changes. Kept the short-signature regression test; test_sig passes under ASan locally and the copy script regenerates cleanly.

This branch has not been deployed

No deployments
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.

3 participants