Botan 3.11.0
Crypto and TLS for C&
sp_hypertree.cpp
Go to the documentation of this file.
1/*
2 * SLH-DSA's Hypertree Logic (FIPS 205, Section 7)
3 * (C) 2023 Jack Lloyd
4 * 2023 Fabian Albert, René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9#include <botan/internal/sp_hypertree.h>
10
11#include <botan/sp_parameters.h>
12#include <botan/internal/buffer_slicer.h>
13#include <botan/internal/buffer_stuffer.h>
14#include <botan/internal/sp_address.h>
15#include <botan/internal/sp_hash.h>
16#include <botan/internal/sp_treehash.h>
17#include <botan/internal/sp_wots.h>
18#include <botan/internal/sp_xmss.h>
19
20namespace Botan {
21
23 const SphincsTreeNode& message_to_sign,
24 const SphincsSecretSeed& secret_seed,
25 XmssTreeIndexInLayer tree_index_in_layer,
26 TreeNodeIndex idx_leaf,
27 const Sphincs_Parameters& params,
28 Sphincs_Hash_Functions& hashes) {
29 BOTAN_ASSERT_NOMSG(out_sig.size() == params.ht_signature_bytes());
30 BufferStuffer ht_signature(out_sig);
31
33 wots_addr.set_tree_address(tree_index_in_layer).set_keypair_address(idx_leaf);
34
36
37 SphincsTreeNode xmss_root;
38 for(HypertreeLayerIndex layer_idx(0); layer_idx < params.d(); layer_idx++) {
39 // The first XMSS tree signs the message, the others their underlying XMSS tree root
40 const SphincsTreeNode& node_to_xmss_sign = (layer_idx == 0U) ? message_to_sign : xmss_root;
41
42 tree_addr.set_layer_address(layer_idx).set_tree_address(tree_index_in_layer);
43 wots_addr.copy_subtree_from(tree_addr).set_keypair_address(idx_leaf);
44
45 xmss_root = xmss_sign_and_pkgen(ht_signature.next<SphincsXmssSignature>(params.xmss_signature_bytes()),
46 node_to_xmss_sign,
47 secret_seed,
48 wots_addr,
49 tree_addr,
50 idx_leaf,
51 params,
52 hashes);
53
54 // Update the indices for the next layer.
55 idx_leaf = TreeNodeIndex(tree_index_in_layer.get() & ((1 << params.xmss_tree_height()) - 1));
56 tree_index_in_layer = tree_index_in_layer >> params.xmss_tree_height();
57 }
58
59 BOTAN_ASSERT_NOMSG(ht_signature.full());
60}
61
62bool ht_verify(const SphincsTreeNode& signed_msg,
64 const SphincsTreeNode& pk_root,
65 XmssTreeIndexInLayer tree_index_in_layer,
66 TreeNodeIndex idx_leaf,
67 const Sphincs_Parameters& params,
68 Sphincs_Hash_Functions& hashes) {
69 BOTAN_ASSERT_NOMSG(ht_sig.size() == params.ht_signature_bytes());
70 BufferSlicer sig_s(ht_sig);
71
75
76 SphincsTreeNode reconstructed_root(params.n());
77
78 // Each iteration reconstructs the root of one XMSS tree of the hypertree
79 for(HypertreeLayerIndex layer_idx(0); layer_idx < params.d(); layer_idx++) {
80 // The first XMSS tree signs the message, the others their underlying XMSS tree root
81 const SphincsTreeNode& current_root = (layer_idx == 0U) ? signed_msg : reconstructed_root;
82
83 tree_addr.set_layer_address(layer_idx);
84 tree_addr.set_tree_address(tree_index_in_layer);
85
86 wots_addr.copy_subtree_from(tree_addr);
87 wots_addr.set_keypair_address(idx_leaf);
88
89 wots_pk_addr.copy_keypair_from(wots_addr);
90
91 const auto wots_pk = wots_public_key_from_signature(
92 current_root, sig_s.take<WotsSignature>(params.wots_bytes()), wots_addr, params, hashes);
93
94 // Compute the leaf node using the WOTS public key.
95 const auto leaf = hashes.T<SphincsTreeNode>(wots_pk_addr, wots_pk);
96
97 // Compute the root node of this subtree.
98 compute_root(StrongSpan<SphincsTreeNode>(reconstructed_root),
99 params,
100 hashes,
101 leaf,
102 idx_leaf,
103 0,
104 sig_s.take<SphincsAuthenticationPath>(params.xmss_tree_height() * params.n()),
105 params.xmss_tree_height(),
106 tree_addr);
107
108 // Update the indices for the next layer.
109 idx_leaf = TreeNodeIndex(tree_index_in_layer.get() & ((1 << params.xmss_tree_height()) - 1));
110 tree_index_in_layer = tree_index_in_layer >> params.xmss_tree_height();
111 }
112
113 BOTAN_ASSERT_NOMSG(sig_s.empty());
114
115 // Check if the root node equals the root node in the public key.
116 return reconstructed_root == pk_root;
117}
118
119} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
std::span< const uint8_t > take(const size_t count)
Helper class to ease in-place marshalling of concatenated fixed-length values.
constexpr std::span< uint8_t > next(size_t bytes)
constexpr bool full() const
Sphincs_Address & set_layer_address(HypertreeLayerIndex layer)
Definition sp_address.h:55
Sphincs_Address & set_tree_address(XmssTreeIndexInLayer tree)
Definition sp_address.h:60
Sphincs_Address & copy_subtree_from(const Sphincs_Address &other)
Definition sp_address.h:103
Sphincs_Address & set_keypair_address(TreeNodeIndex keypair)
Definition sp_address.h:76
Sphincs_Address & copy_keypair_from(const Sphincs_Address other)
Definition sp_address.h:118
void T(std::span< uint8_t > out, const Sphincs_Address &address, const BufferTs &... in)
Definition sp_hash.h:57
uint32_t wots_bytes() const
uint32_t xmss_tree_height() const
uint32_t ht_signature_bytes() const
uint32_t xmss_signature_bytes() const
decltype(auto) size() const noexcept(noexcept(this->m_span.size()))
constexpr T & get() &
Definition strong_type.h:85
Strong< std::vector< uint8_t >, struct SphincsXmssSignature_ > SphincsXmssSignature
Definition sp_types.h:65
Strong< std::vector< uint8_t >, struct SphincsTreeNode_ > SphincsTreeNode
Either an XMSS or FORS tree node or leaf.
Definition sp_types.h:70
Strong< uint64_t, struct XmssTreeIndexInLayer_, EnableArithmeticWithPlainNumber > XmssTreeIndexInLayer
Index of an XMSS tree (unique for just the local hyper-tree layer).
Definition sp_types.h:89
WotsPublicKey wots_public_key_from_signature(const SphincsTreeNode &hashed_message, StrongSpan< const WotsSignature > signature, Sphincs_Address &address, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 8: wots_pkFromSig.
Definition sp_wots.cpp:104
void ht_sign(StrongSpan< SphincsHypertreeSignature > out_sig, const SphincsTreeNode &message_to_sign, const SphincsSecretSeed &secret_seed, XmssTreeIndexInLayer tree_index_in_layer, TreeNodeIndex idx_leaf, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 12: ht_sign.
bool ht_verify(const SphincsTreeNode &signed_msg, StrongSpan< const SphincsHypertreeSignature > ht_sig, const SphincsTreeNode &pk_root, XmssTreeIndexInLayer tree_index_in_layer, TreeNodeIndex idx_leaf, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 13: ht_verify.
Strong< secure_vector< uint8_t >, struct WotsSignature_ > WotsSignature
Definition sp_types.h:80
Strong< secure_vector< uint8_t >, struct SphincsSecretSeed_ > SphincsSecretSeed
Definition sp_types.h:61
Strong< uint32_t, struct TreeNodeIndex_, EnableArithmeticWithPlainNumber > TreeNodeIndex
Index of an individual node inside an XMSS or FORS tree.
Definition sp_types.h:92
Strong< std::vector< uint8_t >, struct SphincsAuthenticationPath_ > SphincsAuthenticationPath
Definition sp_types.h:67
SphincsTreeNode xmss_sign_and_pkgen(StrongSpan< SphincsXmssSignature > out_sig, const SphincsTreeNode &message, const SphincsSecretSeed &secret_seed, Sphincs_Address &wots_addr, Sphincs_Address &tree_addr, std::optional< TreeNodeIndex > idx_leaf, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 10: xmss_sign.
Definition sp_xmss.cpp:19
Strong< uint32_t, struct HypertreeLayerIndex_ > HypertreeLayerIndex
Index of a layer in the XMSS hyper-tree.
Definition sp_types.h:86
void compute_root(StrongSpan< SphincsTreeNode > out, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes, const SphincsTreeNode &leaf, TreeNodeIndex leaf_idx, uint32_t idx_offset, StrongSpan< const SphincsAuthenticationPath > authentication_path, uint32_t total_tree_height, Sphincs_Address &tree_address)