-
Notifications
You must be signed in to change notification settings - Fork 573
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
Conversation
c19b7a4
to
9516b5c
Compare
This PR is now ready! Any review is welcome ❤️ |
There was a problem hiding this 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/tree_hash.h
Outdated
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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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!
There was a problem hiding this 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.
This comment was marked as outdated.
This comment was marked as outdated.
src/lib/pubkey/hss_lms/lms.cpp
Outdated
throw Decoding_Error("Unsupported LMS algorithm type"); | ||
} | ||
throw Decoding_Error("Unsupported LMS algorithm type"); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
rebased to current master |
I force pushed the changes here, to:
|
#3869 is approved; I'll review LMS after this is rebased post merge |
Done. I merged #3869 and rebased. No history rewrite was done. |
There was a problem hiding this 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
* @return The LMS public key. | ||
* @throws Decoding_Error If parsing the public key fails. | ||
*/ | ||
static LMS_PublicKey from_bytes_or_throw(BufferSlicer& slicer); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
c299e55
to
fe90321
Compare
Rebased to fix conflicts on master (likely introduced by merging #3933). |
e82658a
to
5f1db48
Compare
cc8845d
to
10ec77a
Compare
There was a problem hiding this 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.
There was a problem hiding this 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.
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]>
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