Skip to content

slh-dsa: add hazmat module exposing the XMSS layer and message hashes - #1504

Open
jonesmarvin8 wants to merge 1 commit into
RustCrypto:masterfrom
jonesmarvin8:slh-dsa-hazmat
Open

jonesmarvin8 wants to merge 1 commit into
RustCrypto:masterfrom
jonesmarvin8:slh-dsa-hazmat

Conversation

@jonesmarvin8

Copy link
Copy Markdown

Adds an off-by-default hazmat feature to slh-dsa with byte-level wrappers around the crate's existing FIPS 205 code, so other hash-based constructions can be built on it without reimplementing WOTS+ and the XMSS layer:

  • xmss_root, xmss_sign, xmss_pk_from_sig: Algorithms 9–11, at any layer and tree address
  • prf_msg, h_msg: the message hashes of section 4.1
  • n, m, tree_height, xmss_sig_len: sizes for a parameter set

The module only calls existing pub(crate) code; no existing item changes visibility or behavior, and nothing is compiled without the feature.

This complements #1439, which proposes sharing the WOTS+ one-time signature between xmss, lms and slh-dsa. That would cover the chains and checksum, but not the XMSS tree or the message hashes exposed here. If slh-dsa later moves to a shared WOTS+ implementation, these wrappers would call it instead, without changing their API.

Safety notes, also in the module docs:

  • A WOTS+ key pair must never sign two different messages; tracking that is the caller's job.
  • The seeds of an SLH-DSA SigningKey must not be used here: its hypertree's XMSS leaves are the same WOTS+ key pairs, so signing with them would reuse keys and break the SLH-DSA key.
  • Wrong-length slices from the caller panic. The signature and leaf index given to xmss_pk_from_sig may come from anyone, so they return an error instead.
  • With zeroize, the wrappers clear their copies of SK.seed and SK.prf, wiping before any later length check can panic. Temporaries inside the existing XMSS code are not cleared, as elsewhere in the crate.

Tests: the XMSS wrappers reproduce the existing xmss KAT vectors (from slh-dsa-py), the top layer's root matches an SLH-DSA key's public root, every leaf signs and verifies, and the message hashes match the hashes vectors. Also covered: wrong-length signing buffers panic, and malformed signatures and out-of-range leaves are rejected without writing the root. Checked with --no-default-features --features hazmat, --features hazmat,zeroize and --all-features in debug and release, plus cargo fmt --check, cargo doc with -D warnings, and cargo clippy --all-features --all-targets -D warnings. Clippy's remaining findings on 1.94 and stable are in existing files (fors.rs, util.rs, signature_encoding.rs, verifying_key.rs), not in hazmat.rs.

Adds an off-by-default `hazmat` feature with byte-level wrappers around
the crate's own FIPS 205 code: `xmss_root`, `xmss_sign` and
`xmss_pk_from_sig` (Algorithms 9-11, at any layer and tree), `prf_msg`
and `h_msg` (section 4.1), and size helpers. No existing item changes
visibility or behavior.

Wrong-length slices from the caller panic; a malformed signature or leaf
index passed to `xmss_pk_from_sig` returns an error. With `zeroize`, the
wrappers clear their copies of SK.seed and SK.prf.
jonesmarvin8 added a commit to logos-blockchain/logos-execution-zone that referenced this pull request Nov 12, 2026
The wots_tree crate moves into lee as signature::wots::tree, with its
spec beside it, and lee depends on slh-dsa's hazmat feature alone, at
the commit proposed upstream in RustCrypto/signatures#1504. Keys,
signatures and the fixed-seed vectors are unchanged. A malformed
signature passed to hazmat's xmss_pk_from_sig is now an error, which
verification reports as malformed.

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.

1 participant