Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HSS-LMS Signature Algorithm Implementation #3716

Merged
merged 3 commits into from
May 23, 2024

Conversation

FAlbertDev
Copy link
Collaborator

@FAlbertDev FAlbertDev commented Sep 27, 2023

Pull Request Dependencies

Description

This is adding the Hierarchical Signature System (HSS) with Leighton-Micali Hash-Based Signatures (LMS) as defined in RFC 8554.

The first commit (9dddcf6) contains some preparations, mainly common utility functions, and minor cleanup. HSS-LMS is implemented in the second commit (ba36c5e).

For this algorithm, we tried to find a way to generalize the logic to construct a Merkle tree, which is used in all hash-based signature algorithms so far. We introduce the tree_hash.h containing a generalized (and highly flexible) logic for creating Merkle trees. We only apply it for HSS-LMS in this PR but aim to apply it for (at least) SPHINCS+ in a follow-up PR.

If you are interested, you can drop some comments and suggestions.

#3105

@FAlbertDev FAlbertDev force-pushed the pl/lms branch 2 times, most recently from c19b7a4 to 9516b5c Compare September 27, 2023 13:17
@coveralls
Copy link

coveralls commented Sep 28, 2023

Coverage Status

coverage: 91.857% (-0.2%) from 92.028%
when pulling 24c8b6c on Rohde-Schwarz:pl/lms
into bf86f1a on randombit:master.

doc/api_ref/pubkey.rst Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.cpp Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss_lms.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss_lms.cpp Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss_lms_utils.h Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/lm_ots.cpp Show resolved Hide resolved
src/lib/pubkey/hss_lms/lm_ots.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/lms.cpp Outdated Show resolved Hide resolved
src/tests/test_hss_lms.cpp Outdated Show resolved Hide resolved
@FAlbertDev FAlbertDev marked this pull request as ready for review September 29, 2023 14:38
@FAlbertDev
Copy link
Collaborator Author

This PR is now ready! Any review is welcome ❤️

@randombit randombit self-requested a review September 29, 2023 21:14
Copy link
Collaborator

@reneme reneme left a comment

Choose a reason for hiding this comment

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

No full review at all. Mainly just looked at the stuff in src/lib/utils.

src/lib/utils/concepts.h Outdated Show resolved Hide resolved
src/lib/utils/concepts.h Outdated Show resolved Hide resolved
src/lib/utils/loadstor.h Outdated Show resolved Hide resolved
src/lib/utils/stl_util.h Outdated Show resolved Hide resolved
src/lib/utils/stl_util.h Outdated Show resolved Hide resolved
src/lib/utils/tree_hash.h Outdated Show resolved Hide resolved
src/lib/utils/tree_hash.h Outdated Show resolved Hide resolved
Comment on lines 108 to 123
template <concepts::contiguous_strong_type TreeNode,
concepts::strong_span AuthPathSS,
concepts::tree_node_index TreeNodeIndex,
concepts::tree_layer_index TreeLayerIndex,
typename Address>
requires concepts::tree_address<Address, TreeLayerIndex, TreeNodeIndex>
inline void treehash(
StrongSpan<TreeNode> out_root,
std::optional<AuthPathSS> out_auth_path,
std::optional<TreeNodeIndex> leaf_idx,
size_t node_size,
TreeLayerIndex total_tree_height,
uint32_t idx_offset,
concepts::tree_hash_node_pair<TreeNodeIndex, TreeLayerIndex, Address, StrongSpan<TreeNode>> auto node_pair_hash,
concepts::tree_gen_leaf<TreeNodeIndex, TreeLayerIndex, Address, StrongSpan<TreeNode>> auto gen_leaf,
Address& tree_address) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

😲

Any chance we could wrap that into a reasonable class that removes some complexity from this interface? Off the top of my head, I don't know enough to give useful suggestions. Though, on first glance, that seems like a nightmare to use and/or understand.

Can we go through the usage of this in a pair-programming session at one point please?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, I admit that this construct looked much better in my head. The goal of this template hell is that the calling party only calls this function with its own strong types while all types of treehash are deduced automatically without the need to pass any template parameters. But yeah, I would love to get your input on this in a pair-programming session!

Copy link
Owner

@randombit randombit left a comment

Choose a reason for hiding this comment

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

Started a review. I haven't gotten into the core implementation yet so this is just some initial comments, I will do a full review asap.

src/build-data/oids.txt Show resolved Hide resolved
src/lib/utils/stl_util.h Outdated Show resolved Hide resolved
src/lib/utils/tree_hash.h Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/lms.h Show resolved Hide resolved
src/lib/pubkey/hss_lms/lms.h Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss_lms_utils.h Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss_lms.h Outdated Show resolved Hide resolved
reneme

This comment was marked as outdated.

reneme

This comment was marked as outdated.

@FAlbertDev

This comment was marked as outdated.

throw Decoding_Error("Unsupported LMS algorithm type");
}
throw Decoding_Error("Unsupported LMS algorithm type");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use unique error messages: If you see one of those in some bug report log, you'll want to know which code path was taken.

Copy link
Collaborator

Choose a reason for hiding this comment

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

... same below, for the hash functions.

src/lib/pubkey/hss_lms/lms.cpp Outdated Show resolved Hide resolved
reneme

This comment was marked as outdated.

@lieser
Copy link
Collaborator

lieser commented Oct 31, 2023

rebased to current master

@reneme
Copy link
Collaborator

reneme commented Jan 12, 2024

I force pushed the changes here, to:

  1. take advantage of the changes in Refactor: Final iteration on load/store #3869
  2. squash and clean up the history

@reneme
Copy link
Collaborator

reneme commented Feb 16, 2024

Rebased after the underlying #3869 needed to get conflicts resolved after #3908 was merged. Also, the code here needed minor conflict resolving due to #3908.

@randombit
Copy link
Owner

#3869 is approved; I'll review LMS after this is rebased post merge

@reneme
Copy link
Collaborator

reneme commented Mar 21, 2024

I'll review LMS after this is rebased post merge

Done. I merged #3869 and rebased. No history rewrite was done.

Copy link
Owner

@randombit randombit left a comment

Choose a reason for hiding this comment

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

Various small comments/questions but overall lgtm

src/lib/pubkey/hss_lms/hss_lms.h Outdated Show resolved Hide resolved
* @return The LMS public key.
* @throws Decoding_Error If parsing the public key fails.
*/
static LMS_PublicKey from_bytes_or_throw(BufferSlicer& slicer);
Copy link
Owner

Choose a reason for hiding this comment

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

This is an internal API so maybe doesn’t matter that much but passing a BufferSlicer as a parameter feels very odd to me. I would think you would just pass a span and then as required construct a BufferSlicer to perform your parsing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree that we can pass a span here instead. This would be suitable but inconsistent with signature parsing, where passing the slicer is quite sensible (see below). I have no hard feelings for both options.

Copy link
Collaborator

@reneme reneme Apr 23, 2024

Choose a reason for hiding this comment

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

Perhaps my two cents; talking from experience in #4024: I totally agree, that any loosely coupled API shouldn't pass around BufferSlicer or BufferStuffer references. Though, for tightly coupled internal APIs (e.g. utility functions in the same compilation unit), I find this very much convenient.

Accepting a span, as @randombit suggested, has the drawback that the caller must know how many bytes the callee will want to consume or emit. Usually, that can be determined, but it typically requires some extra calculations that were already done to determine the overall size of the final serialized structure. Just passing the Buffer*** reference and trusting that the callee will be responsible, is saving some cycles and also noise in the code.

That said: We should always remember to validate that the Buffer*** is full/empty when expected at the very end of the marshalling, to check that everything checked out as expected.

src/lib/pubkey/hss_lms/lms.h Show resolved Hide resolved
src/lib/pubkey/hss_lms/lm_ots.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/lm_ots.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/lm_ots.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss_lms.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/lms.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/lms.cpp Outdated Show resolved Hide resolved
@reneme reneme force-pushed the pl/lms branch 2 times, most recently from c299e55 to fe90321 Compare April 8, 2024 11:32
@reneme
Copy link
Collaborator

reneme commented Apr 8, 2024

Rebased to fix conflicts on master (likely introduced by merging #3933).

@randombit randombit modified the milestones: Botan 3.4.0, Botan 3.5.0 Apr 8, 2024
@FAlbertDev FAlbertDev force-pushed the pl/lms branch 2 times, most recently from e82658a to 5f1db48 Compare April 23, 2024 10:53
src/lib/utils/int_utils.h Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.h Outdated Show resolved Hide resolved
Copy link
Collaborator

@reneme reneme left a comment

Choose a reason for hiding this comment

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

Just a few ad-hoc remarks. Will go through the implementation one final time tomorrow.

doc/api_ref/pubkey.rst Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.h Show resolved Hide resolved
src/lib/utils/concepts.h Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@reneme reneme left a comment

Choose a reason for hiding this comment

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

Still didn't find time for another full review pass. But no general objection to merging this from my side.

src/lib/pubkey/hss_lms/hss.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.cpp Show resolved Hide resolved
src/lib/pubkey/hss_lms/hss.cpp Outdated Show resolved Hide resolved
src/lib/pubkey/hss_lms/lms.cpp Outdated Show resolved Hide resolved
FAlbertDev and others added 3 commits May 23, 2024 14:41
Some cleanup and addition of common utility functions

Co-authored-by: Philippe Lieser <[email protected]>
Co-authored-by: René Meusel <[email protected]>
Implementation of the Hierarchical Signature System (HSS) with
Leighton-Micali Hash-Based Signatures (LMS). Based on RFC 8554.

Co-authored-by: Philippe Lieser <[email protected]>
Co-authored-by: René Meusel <[email protected]>
Integration into pk_algs, tests and documentation.

Co-authored-by: Philippe Lieser <[email protected]>
Co-authored-by: René Meusel <[email protected]>
@FAlbertDev FAlbertDev merged commit 19567e3 into randombit:master May 23, 2024
43 checks passed
@FAlbertDev FAlbertDev deleted the pl/lms branch May 23, 2024 13:25
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.

5 participants