Skip to content

fix: LMOTS pattern, add HSS variant (LMS family) - #1029

Open
Mehrn0ush wants to merge 4 commits into
CycloneDX:masterfrom
Mehrn0ush:fix/lms-hss-variant-model
Open

Mehrn0ush wants to merge 4 commits into
CycloneDX:masterfrom
Mehrn0ush:fix/lms-hss-variant-model

Conversation

@Mehrn0ush

Copy link
Copy Markdown
Contributor

Hi,
LMOTS had a treeHeight parameter it shouldn't — LM-OTS doesn't use a Merkle tree, so there's no height involved. Swapped it for the Winternitz parameter w, which is what actually distinguishes the RFC's parameter sets (LMOTS_SHA256_N32_W1/W2/W4/W8).

Also added HSS, which was missing entirely. It's just the multi-level LMS construction, parameterized by number of levels (L), so the pattern is intentionally minimal — no hash/M/H, since those come from whichever LMS parameter set each level uses.

LMS itself was already correct.

"LMOTS[_{hashAlgorithm}][_N{bytesPerNode}][_W{winternitzParameter}]"
"HSS[_L{levels}]"

One question — LMOTS still reuses {bytesPerNode} for its N parameter, but RFC 8554 calls this n — the LM-OTS hash output length, not a node value (LM-OTS has no tree nodes). Should this be renamed to something like {hashOutputLength} on LMOTS, keeping {bytesPerNode} only on LMS where it's accurate? Didn't want to bundle a naming change into this fix, so leaving it open — happy to push a follow-up if there's agreement either way.

Closes #1028.

Align LMOTS with RFC 8554 Table 1 (N and W, not tree height) and add
the HSS levels pattern from RFC 8554 §6 / NIST SP 800-208.
Signed-off-by: Mehrn0ush <mehrnoush.vaseghi@gmail.com>
@Mehrn0ush
Mehrn0ush requested a review from a team as a code owner August 16, 2026 14:00
@Mehrn0ush Mehrn0ush changed the title Fix LMOTS pattern, add HSS variant (LMS family) fix: LMOTS pattern, add HSS variant (LMS family) Aug 16, 2026
@stevespringett
stevespringett requested a review from bhess August 20, 2026 13:23
@stevespringett stevespringett added the cap: cryptography-registry Capability: Cryptography Registry label Aug 20, 2026
@jvdsn

jvdsn commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor

Also added HSS, which was missing entirely. It's just the multi-level LMS construction, parameterized by number of levels (L), so the pattern is intentionally minimal — no hash/M/H, since those come from whichever LMS parameter set each level uses.

Would there be any way to express that? Dependencies?

Note for reviewers, RFC 8554 explicitly allows a lot of flexibility:

We specifically allow different LMS levels to use different parameter
sets. For example, the 0-th LMS public key (the root) may use the
LMS_SHA256_M32_H15 parameter set, while the 1-th public key may use
LMS_SHA256_M32_H10.

@Mehrn0ush

Copy link
Copy Markdown
Contributor Author

Hi,
@jvdsn thank you for reviewing this PR.
In this schema, variant only has pattern/primitive/standard, no dependency field, so there's no structural way to express this today. XMSSMT handles its multi-tree case by encoding {h}/{d} directly in the pattern string, but that only works because XMSS-MT levels share one parameter set. HSS can't use the same trick since RFC 8554 allows each level to pick an independent LMS parameter set. Left HSS[_L{levels}] as-is for now — a real fix would need a schema change to support per-level composition, which is bigger than this PR. (For what it's worth, I also checked the v2 cryptography schema — it moves to a free-text parameterSetIdentifier per algorithm instance rather than family-level patterns, and doesn't add a composition mechanism either, so this looks like a genuine open gap rather than something already solved elsewhere.)
Happy to adjust further if maintainers have thoughts on this — let me know if any additional changes are needed here.

@bhess

bhess commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

If I understand correctly, we would like to describe an ordered sequence of LMS parameter sets for HSS, one per level, including the associated LMOTS parameter sets. Is that correct?

What we could do is extending the naming-pattern convention to support repetition. For example, * for zero or more occurrences or + for one or more, and references to other patterns, such as <LMS> and <LMOTS>.
This would require documenting the new notation, but no structural change to the JSON schema, since pattern is already a string. It could keep this within the existing naming-pattern approach.

@Mehrn0ush

Copy link
Copy Markdown
Contributor Author

Yes, that’s exactly it — HSS is an ordered sequence of L levels, each with its own LMS and LMOTS parameter set (RFC 8554 secion 6; SP 800-208 narrows the allowed sets but keeps the per-level structure).

I like extending the naming-pattern notation rather than changing the schema. Three things I’d want covered when we document it:

  • is already a literal in SPAKE2+…. Either restrict quantifiers to follow a ) group only, or define an escape.
    needs a resolution rule: a reference to the variant pattern whose leading literal is LMS (not the family — the LMS family also holds LMOTS), with leading literals unique across the registry.
    The pattern can’t tie the repeat count to {levels}; that would be a stated rule, like the join rule in CBOM: add protocol registry schema #1010.
    Something like HSS[L{levels}][(_)+], root level first.

Since this touches the convention for the whole registry, do you suggest keeping this PR as the LMOTS/HSS correctness fix and doing the notation + full HSS pattern as a follow-up (happy to open it). Fine to fold it in here instead if you prefer. @bhess

Extend the algorithm naming convention with variant references (<Name>)
and repeated groups ((...)+) to describe ordered LMS/LMOTS pairs in HSS,
and document the full notation on the pattern property, including the
constructs already in use (top-level alternation, plain grouping,
literal -, _, /, +). HSS pairs are ordered root level first; when both
{levels} and pairs are present their number shall match; omitted
parameters are unspecified and not inherited between pairs. Rename the
LMOTS N placeholder to hashOutputLength (RFC 8554 n, in bytes), make the
SHA256/SHAKE tokens explicit, and add RFC 9858 to the LMS family.
The JSON structure is unchanged; consumers interpreting naming patterns
may need to support the new notation.

Signed-off-by: Mehrn0ush <mehrnoush.vaseghi@gmail.com>
@Mehrn0ush

Mehrn0ush commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor Author

Pushed the extended approach following @bhess's suggestion. pattern now documents the notation ({} placeholders, | alternation pattern-wide or in a group, ( ) grouping, [ ] optional, ( )+ repetition, references resolved by leading literal; unique and non-cyclic).
Only + is new, and it is literal elsewhere, so SPAKE2+ is unaffected. All existing patterns parse under the documented grammar.
HSS is HSS[L{levels}][(_)+], root level first, pairs = L when both present;
HSS_L2 and pair-only names remain valid partial identifications; omitted parameters are not inherited between pairs. LMOTS N → {hashOutputLength} (bytes); hash tokens (SHA256|SHAKE) per RFC 8554/9858; RFC 9858 added.
Compatibility: JSON structure unchanged; consumers interpreting pattern strings may need updates.

One thing @bhess to confirm: under the written grammar FFDH(E)[-{namedGroup}] reads as a required E (FFDHE…); if FFDH[E] was intended, I can open a separate PR.

@stevespringett

Copy link
Copy Markdown
Member

@bhess Can you please review when you get a chance.

@bhess bhess 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.

Thanks for this update!

One thing @bhess to confirm: under the written grammar FFDH(E)[-{namedGroup}] reads as a required E (FFDHE…); if FFDH[E] was intended, I can open a separate PR.

Right, the E is optional (stands for ephemeral). Thanks for the catch, and for offering to fix this!

Comment thread schema/cryptography-defs.schema.json Outdated
"title": "Standard Name",
"description": "Defines the pattern used to construct the complete algorithm name. Placeholders are defined by {} for algorithm-specific properties."
"title": "Naming Pattern",
"description": "Defines the pattern used to construct the algorithm name. Notation: `{name}` is a placeholder for an algorithm-specific property; `|` separates alternatives, of which exactly one is used, either across the whole pattern or within a parenthesized group such as `(a|b)`; `( )` groups content, and a group without `|` is plain grouping; `[ ]` marks optional content; `( )+` marks one or more repetitions of the group; `<Name>` references the variant pattern in the cryptographic algorithm definitions registry whose leading literal is `Name`, the leading literal being the initial literal token before the first notation construct (for example `LMS` in `LMS[_(SHA256|SHAKE)]...`), and stands for a name constructed from that pattern, preserving its optional parts. Braces, brackets, parentheses, angle brackets, `|`, and a `+` directly following `)` are notation and are not part of the constructed name; every other character is literal, including `-`, `_`, `/`, and a `+` elsewhere (as in `SPAKE2+`). A reference shall resolve to exactly one variant pattern and shall not be cyclic. Omitted optional parts mean that the corresponding parameters are unspecified, so a name following this notation may be a partial identification rather than a fully specified parameter configuration. For `LMS` and `LMOTS`, `{bytesPerNode}` and `{hashOutputLength}` are measured in bytes. For `HSS`, repeated `LMS`/`LMOTS` pairs are ordered from the root level downward; when both `{levels}` and the repeated pairs are present, the number of pairs shall equal `{levels}`; omission of the pairs leaves the per-level parameters unspecified, and parameters omitted from one pair are unspecified and are not inherited from another pair."

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.

Thanks a lot for writing this up, and for checking that all existing patterns parse under it, that was really helpful!

One thought, and I'm curious what you think: the description is what implementers see in the generated docs, and I wonder whether the full grammar might be a bit heavy there. Maybe we could keep a short list of the constructs with examples in the schema, and move the detailed grammar into the updated CBOM guide, where there's more room for edge cases and examples?

As a starting point:

Defines the pattern used to construct the algorithm name. {name} is a placeholder for an algorithm-specific value, [ ] marks optional content, | separates alternatives of which exactly one is used, across the whole pattern or within ( ), and ( )+ repeats a group one or more times. <Name> stands for a name built from the variant pattern whose text before the first notation character is Name, for example <LMS>. All other characters, such as -, _ and the + in SPAKE2+, are part of the name. An omitted optional part means the value is unspecified, except for a fixed literal such as [-PKCS7], whose absence selects the variant without it. For HSS, the LMS/LMOTS pairs are listed per level, starting at the root; when both {levels} and pairs are given, their numbers shall be equal.

@stevespringett, curious to hear what you think.

Keep a construct summary in the schema (placeholders, optional
content, alternation, group repetition, <Name> references, literal
+, HSS ordering/count). Move the detailed grammar to the CBOM
guide. Distinguish omitted parameters from omitted fixed literals
such as [-PKCS7] or [E].

Signed-off-by: Mehrn0ush <mehrnoush.vaseghi@gmail.com>

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

cap: cryptography-registry Capability: Cryptography Registry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Defect]: LMOTS parameters and add missing HSS variant (LMS family)

5 participants