Botan 3.5.0
Crypto and TLS for C&
sp_hash.cpp
Go to the documentation of this file.
1/*
2 * SPHINCS+ Hashes
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/internal/stl_util.h>
12
13#include <botan/assert.h>
14#include <botan/exceptn.h>
15#include <botan/hash.h>
16#include <botan/sp_parameters.h>
17
18#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
19 #include <botan/internal/sp_hash_shake.h>
20#endif
21
22#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2)
23 #include <botan/internal/sp_hash_sha2.h>
24#endif
25
26#include <memory>
27
28namespace Botan {
29
31 const SphincsPublicSeed& pub_seed) :
32 m_sphincs_params(sphincs_params), m_pub_seed(pub_seed) {}
33
34std::unique_ptr<Sphincs_Hash_Functions> Sphincs_Hash_Functions::create(const Sphincs_Parameters& sphincs_params,
35 const SphincsPublicSeed& pub_seed) {
36 switch(sphincs_params.hash_type()) {
38#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2)
39 return std::make_unique<Sphincs_Hash_Functions_Sha2>(sphincs_params, pub_seed);
40#else
41 throw Not_Implemented("SPHINCS+ with SHA-256 is not available in this build");
42#endif
43
45#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
46 return std::make_unique<Sphincs_Hash_Functions_Shake>(sphincs_params, pub_seed);
47#else
48 throw Not_Implemented("SPHINCS+ with SHAKE is not available in this build");
49#endif
50
52 throw Not_Implemented("Haraka is not yet implemented");
53 }
55}
56
57namespace {
58
59template <typename T>
60T from_first_n_bits(const uint32_t nbits, std::span<const uint8_t> bytes) {
61 using wrapped_type = typename T::wrapped_type;
62
63 constexpr const auto outsize = sizeof(wrapped_type);
64 BOTAN_ASSERT_NOMSG(nbits <= bytes.size() * 8);
65 BOTAN_ASSERT_NOMSG(bytes.size() <= outsize);
66
67 // The input buffer might shorter than the byte-length of the desired
68 // integer type. This prepends \0-bytes accordingly.
69 std::array<uint8_t, outsize> normalized_bytes = {};
70 std::copy(bytes.rbegin(), bytes.rend(), normalized_bytes.rbegin());
71 const auto bits = load_be<wrapped_type>(normalized_bytes.data(), 0);
72
73 return T(bits & (~wrapped_type(0) >> (8 * outsize - nbits)));
74}
75
76} // namespace
77
78std::tuple<SphincsHashedMessage, XmssTreeIndexInLayer, TreeNodeIndex> Sphincs_Hash_Functions::H_msg(
79 StrongSpan<const SphincsMessageRandomness> r, const SphincsTreeNode& root, std::span<const uint8_t> message) {
80 const auto digest = H_msg_digest(r, root, message);
81
82 // The following calculates the message digest and indices from the
83 // raw message digest. See Algorithm 20 (spx_sign) in SPHINCS+ 3.1
84 const auto& p = m_sphincs_params;
85 BufferSlicer s(digest);
86 auto msg_hash = s.copy<SphincsHashedMessage>(p.fors_message_bytes());
87 auto tree_index_bytes = s.take(p.tree_digest_bytes());
88 auto leaf_index_bytes = s.take(p.leaf_digest_bytes());
90
91 auto tree_index = from_first_n_bits<XmssTreeIndexInLayer>(p.h() - p.xmss_tree_height(), tree_index_bytes);
92 auto leaf_index = from_first_n_bits<TreeNodeIndex>(p.xmss_tree_height(), leaf_index_bytes);
93 return {std::move(msg_hash), tree_index, leaf_index};
94}
95
96} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:137
auto copy(const size_t count)
Definition stl_util.h:89
bool empty() const
Definition stl_util.h:129
std::span< const uint8_t > take(const size_t count)
Definition stl_util.h:98
virtual std::vector< uint8_t > H_msg_digest(StrongSpan< const SphincsMessageRandomness > r, const SphincsTreeNode &root, std::span< const uint8_t > message)=0
const Sphincs_Parameters & m_sphincs_params
Definition sp_hash.h:101
Sphincs_Hash_Functions(const Sphincs_Parameters &sphincs_params, const SphincsPublicSeed &pub_seed)
Definition sp_hash.cpp:30
static std::unique_ptr< Sphincs_Hash_Functions > create(const Sphincs_Parameters &sphincs_params, const SphincsPublicSeed &pub_seed)
Definition sp_hash.cpp:34
std::tuple< SphincsHashedMessage, XmssTreeIndexInLayer, TreeNodeIndex > H_msg(StrongSpan< const SphincsMessageRandomness > r, const SphincsTreeNode &root, std::span< const uint8_t > message)
Definition sp_hash.cpp:78
Sphincs_Hash_Type hash_type() const
FE_25519 T
Definition ge.cpp:34
Gf448Elem root(const Gf448Elem &elem)
Compute the root of elem in the field.
@ Haraka
Haraka is currently not supported.
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:467