Botan 3.11.0
Crypto and TLS for C&
sp_hash.cpp
Go to the documentation of this file.
1/*
2 * SLH-DSA Hash Function Interface
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_hash.h>
10
11#include <botan/assert.h>
12#include <botan/exceptn.h>
13#include <botan/hash.h>
14#include <botan/sp_parameters.h>
15#include <botan/internal/buffer_slicer.h>
16#include <memory>
17
18#if defined(BOTAN_HAS_SPHINCS_PLUS_SHAKE_BASE)
19 #include <botan/internal/sp_hash_shake.h>
20#endif
21
22#if defined(BOTAN_HAS_SPHINCS_PLUS_SHA2_BASE)
23 #include <botan/internal/sp_hash_sha2.h>
24#endif
25
26namespace Botan {
27
29 const SphincsPublicSeed& pub_seed) :
30 m_sphincs_params(sphincs_params), m_pub_seed(pub_seed) {}
31
32std::unique_ptr<Sphincs_Hash_Functions> Sphincs_Hash_Functions::create(const Sphincs_Parameters& sphincs_params,
33 const SphincsPublicSeed& pub_seed) {
34 switch(sphincs_params.hash_type()) {
36#if defined(BOTAN_HAS_SPHINCS_PLUS_SHA2_BASE)
37 return std::make_unique<Sphincs_Hash_Functions_Sha2>(sphincs_params, pub_seed);
38#else
39 throw Not_Implemented("SLH-DSA (or SPHINCS+) with SHA-256 is not available in this build");
40#endif
41
43#if defined(BOTAN_HAS_SPHINCS_PLUS_SHAKE_BASE)
44 return std::make_unique<Sphincs_Hash_Functions_Shake>(sphincs_params, pub_seed);
45#else
46 throw Not_Implemented("SLH-DSA (or SPHINCS+) with SHAKE is not available in this build");
47#endif
48
50 throw Not_Implemented("Haraka is not implemented");
51 }
53}
54
55namespace {
56
57template <typename T>
58T from_first_n_bits(const uint32_t nbits, std::span<const uint8_t> bytes) {
59 using wrapped_type = typename T::wrapped_type;
60
61 constexpr const auto outsize = sizeof(wrapped_type);
62 BOTAN_ASSERT_NOMSG(nbits <= bytes.size() * 8);
63 BOTAN_ASSERT_NOMSG(bytes.size() <= outsize);
64
65 // The input buffer might shorter than the byte-length of the desired
66 // integer type. This prepends \0-bytes accordingly.
67 std::array<uint8_t, outsize> normalized_bytes = {};
68 std::copy(bytes.rbegin(), bytes.rend(), normalized_bytes.rbegin());
69 const auto bits = load_be<wrapped_type>(normalized_bytes.data(), 0);
70
71 return T(bits & (~wrapped_type(0) >> (8 * outsize - nbits)));
72}
73
74} // namespace
75
76std::tuple<SphincsHashedMessage, XmssTreeIndexInLayer, TreeNodeIndex> Sphincs_Hash_Functions::H_msg(
78 const auto digest = H_msg_digest(r, root, message);
79
80 // The following calculates the message digest and indices from the
81 // raw message digest. See FIPS 205, Algorithm 19, Line 5-10.
82 const auto& p = m_sphincs_params;
83 BufferSlicer s(digest);
84 auto msg_hash = s.copy<SphincsHashedMessage>(p.fors_message_bytes());
85 auto tree_index_bytes = s.take(p.tree_digest_bytes());
86 auto leaf_index_bytes = s.take(p.leaf_digest_bytes());
88
89 auto tree_index = from_first_n_bits<XmssTreeIndexInLayer>(p.h() - p.xmss_tree_height(), tree_index_bytes);
90 auto leaf_index = from_first_n_bits<TreeNodeIndex>(p.xmss_tree_height(), leaf_index_bytes);
91 return {std::move(msg_hash), tree_index, leaf_index};
92}
93
94} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:163
auto copy(const size_t count)
std::span< const uint8_t > take(const size_t count)
const SphincsPublicSeed & m_pub_seed
Definition sp_hash.h:103
const Sphincs_Parameters & m_sphincs_params
Definition sp_hash.h:102
Sphincs_Hash_Functions(const Sphincs_Parameters &sphincs_params, const SphincsPublicSeed &pub_seed)
Definition sp_hash.cpp:28
std::tuple< SphincsHashedMessage, XmssTreeIndexInLayer, TreeNodeIndex > H_msg(StrongSpan< const SphincsMessageRandomness > r, const SphincsTreeNode &root, const SphincsMessageInternal &message)
Definition sp_hash.cpp:76
static std::unique_ptr< Sphincs_Hash_Functions > create(const Sphincs_Parameters &sphincs_params, const SphincsPublicSeed &pub_seed)
Definition sp_hash.cpp:32
virtual std::vector< uint8_t > H_msg_digest(StrongSpan< const SphincsMessageRandomness > r, const SphincsTreeNode &root, const SphincsMessageInternal &message)=0
Sphincs_Hash_Type hash_type() const
Gf448Elem root(const Gf448Elem &elem)
Compute the root of elem in the field.
Strong< std::vector< uint8_t >, struct SphincsTreeNode_ > SphincsTreeNode
Either an XMSS or FORS tree node or leaf.
Definition sp_types.h:70
@ Haraka
Haraka is currently not supported.
Strong< std::vector< uint8_t >, struct SphincsPublicSeed_ > SphincsPublicSeed
Definition sp_types.h:60
Strong< std::vector< uint8_t >, struct SphincsHashedMessage_ > SphincsHashedMessage
Definition sp_types.h:59
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504
M' representation of FIPS 205 (the input to slh_sign_internal and slh_verify_internal).
Definition sp_types.h:52